[submodule "external/nuget-buildtasks"]
path = external/nuget-buildtasks
url = git://github.com/mono/NuGet.BuildTasks
-[submodule "external/buildtools"]
- path = external/buildtools
- url = git://github.com/mono/buildtools.git
[submodule "external/cecil-legacy"]
path = external/cecil-legacy
url = git://github.com/mono/cecil.git
# Process this file with autoconf to produce a configure script.
#AC_PREREQ([2.62])
-AC_INIT(mono, [5.3.0],
+AC_INIT(mono, [5.5.0],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
AC_CONFIG_SRCDIR([README.md])
with_sgen_default_concurrent=yes
;;
*-*-nacl*)
- CPPFLAGS="$CPPFLAGS -DGC_LINUX_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP"
- if test "x$disable_munmap" != "xyes"; then
- CPPFLAGS="$CPPFLAGS -DUSE_MUNMAP"
- fi
- libmono_cflags="-D_REENTRANT"
- libdl=
- libgc_threads=pthreads
- use_sigposix=yes
- ikvm_native=no
- AC_DEFINE(DISABLE_SOCKETS,1,[Disable sockets support])
- AC_DEFINE(DISABLE_ATTACH, 1, [Disable agent attach support])
+ echo "nacl no longer supported."
+ exit 1
;;
*-*-hpux*)
CPPFLAGS="$CPPFLAGS -DGC_HPUX_THREADS -D_HPUX_SOURCE -D_XOPEN_SOURCE_EXTENDED -D_REENTRANT"
AM_CONDITIONAL(DISABLE_LIBRARIES, test x$enable_libraries = xno)
-case $host in
-*nacl* ) with_shared_mono=yes;;
-esac
-
if test "x$host_win32" = "xyes"; then
# Boehm GC requires the runtime to be in its own dll
with_static_mono=no
AC_DEFINE_UNQUOTED(MONO_ZERO_LEN_ARRAY, 1, [Length of zero length arrays])
])
-AC_CHECK_HEADERS(nacl/nacl_dyncode.h)
-
dnl ***********************************
dnl *** Checks for signals
dnl ***********************************
dnl **********************************
dnl *** epoll ***
dnl **********************************
- if test "x$ac_cv_header_nacl_nacl_dyncode_h" = "xno"; then
- AC_CHECK_HEADERS(sys/epoll.h)
- haveepoll=no
- AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], )
- if test "x$haveepoll" = "xyes" -a "x$ac_cv_header_sys_epoll_h" = "xyes"; then
- AC_DEFINE(HAVE_EPOLL, 1, [epoll supported])
- fi
+ AC_CHECK_HEADERS(sys/epoll.h)
+ haveepoll=no
+ AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], )
+ if test "x$haveepoll" = "xyes" -a "x$ac_cv_header_sys_epoll_h" = "xyes"; then
+ AC_DEFINE(HAVE_EPOLL, 1, [epoll supported])
fi
havekqueue=no
AM_CONDITIONAL(ENABLE_DTRACE, [test x$enable_dtrace = xyes])
AM_CONDITIONAL(DTRACE_G_REQUIRED, [test x$dtrace_g = xyes])
-dnl **************
-dnl *** NaCl ***
-dnl **************
-
-AC_ARG_ENABLE(nacl_codegen, [ --enable-nacl-codegen Enable Native Client code generation], enable_nacl_codegen=$enableval, enable_nacl_codegen=no)
-AC_ARG_ENABLE(nacl_gc, [ --enable-nacl-gc Enable Native Client garbage collection], enable_nacl_gc=$enableval, enable_nacl_gc=no)
-
-AM_CONDITIONAL(NACL_CODEGEN, test x$enable_nacl_codegen != xno)
-
-dnl
-dnl Hack to use system mono for operations in build/install not allowed in NaCl.
-dnl
-nacl_self_host=""
-if test "x$ac_cv_header_nacl_nacl_dyncode_h" = "xyes"; then
- nacl_self_host="nacl_self_host"
-fi
-AC_SUBST(nacl_self_host)
-
-if test "x$enable_nacl_codegen" = "xyes"; then
- MONO_NACL_ALIGN_MASK_OFF=1
- AC_DEFINE(TARGET_NACL, 1, [...])
- AC_DEFINE(__native_client_codegen__, 1, [...])
-fi
-if test "x$enable_nacl_gc" = "xyes"; then
- if test "x$TARGET" = "xAMD64" -o "x$TARGET" = "xX86"; then
- INSTRUMENT_CFLAG="-finstrument-for-thread-suspension"
- else
- # Not yet implemented
- INSTRUMENT_CFLAG=""
- fi
- CPPFLAGS="$CPPFLAGS $INSTRUMENT_CFLAG -D__native_client_gc__"
-fi
-AC_SUBST(MONO_NACL_ALIGN_MASK_OFF)
-
dnl **************************
dnl *** AOT cross offsets ***
dnl **************************
mingw*)
;;
esac
- case "$host" in
- x86_64-*-nacl*)
- AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers])
- sizeof_register=8
- ;;
- esac
;;
sparc*-*-*)
if test "x$ac_cv_sizeof_void_p" = "x8"; then
ACCESS_UNALIGNED="no"
CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
;;
-# TODO: make proper support for NaCl host.
-# arm*-*nacl)
-# TARGET=ARM;
-# arch_target=arm;
-# ACCESS_UNALIGNED="no"
-# AOT_SUPPORTED="no"
-# ;;
aarch64-*)
# https://lkml.org/lkml/2012/7/15/133
TARGET=ARM64
sizeof_register=8
target_byte_order=G_BIG_ENDIAN
;;
- x86_64-*-nacl)
- TARGET=AMD64
- arch_target=amd64
- AC_DEFINE(TARGET_AMD64, 1, [...])
- AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers])
- sizeof_register=8
- ;;
-# TODO: make proper support for NaCl target.
-# arm*-*nacl)
-# TARGET=ARM
-# arch_target=arm
-# AC_DEFINE(TARGET_ARM, 1, [...])
-# ACCESS_UNALIGNED="no"
-# sizeof_register=4
-# CPPFLAGS="$CPPFLAGS \
-# -D__ARM_EABI__ \
-# -D__arm__ \
-# -D__portable_native_client__ \
-# -Dtimezone=_timezone \
-# -DDISABLE_SOCKETS \
-# -DDISABLE_ATTACH \
-# -DUSE_NEWLIB"
- # Can't use tls, since it depends on the runtime detection of tls offsets
- # in mono-compiler.h
-# with_tls=pthread
-# ;;
- i686-*-nacl)
- TARGET=X86
- arch_target=x86
- AC_DEFINE(TARGET_X86, 1, [...])
- sizeof_register=4
- ;;
arm*-linux-*)
TARGET=ARM;
arch_target=arm;
AM_CONDITIONAL(ENABLE_INTERPRETER, [test x$enable_interpreter = xyes])
+if test "x$enable_interpreter" = "xyes" || test "x$mono_feature_disable_jit" != "xyes"; then
+ AC_DEFINE(HAVE_ONLINE_VES, 1, [Some VES is available at runtime])
+fi
+
+AM_CONDITIONAL(HAVE_ONLINE_VES, [test x$enable_interpreter = xyes] || [test x$mono_feature_disable_jit != xyes])
dnl
dnl Simple Generational checks (sgen)
#define G_HAVE_ISO_VARARGS
#endif
-#if defined (__native_client__) || defined (HOST_WATCHOS)
+#if defined (HOST_WATCHOS)
#undef G_BREAKPOINT
#define G_BREAKPOINT()
#endif
gchar *
g_get_current_dir (void)
{
-#ifdef __native_client__
- char *buffer;
- if ((buffer = g_getenv("NACL_PWD"))) {
- buffer = g_strdup(buffer);
- } else {
- buffer = g_strdup(".");
- }
- return buffer;
-#else
int s = 32;
char *buffer = NULL, *r;
gboolean fail;
* so we return the buffer here since it has a pointer to the valid string
*/
return buffer;
-#endif
}
-Subproject commit d207a517b2655cd4af5dd3b7735d8f6e139fafae
+Subproject commit 1563f6ea5ba2f4c6f3e9c6e625ee8b16e3a1d39e
-Subproject commit 1f303af76929ed6cd942f51f4177afc93c797f00
+Subproject commit fe467c0593d199e5d4d29be9c69c5d487449dd8b
+++ /dev/null
-Subproject commit b5cc6e6ab5f71f6c0be7b730058b426e92528479
-Subproject commit 0b523fa7e0f2f83cc67e4c19f1f769e68d717562
+Subproject commit f64903c0e069224aaac7de243fa0a3b17684b4dd
-Subproject commit 5b7e0d739fa65bb7b1c2230df875d37a55b74d10
+Subproject commit bc22b1f08545261b7dc18f312dcd5b4f04768ecb
-Subproject commit 814f76de6a972c5c3dd3ec6b10dc900fd73d08d2
+Subproject commit 48dba73801e804e89f00311da99d873f9c550278
-Subproject commit 88b67c42ca8b7d58141c176b46749819bfcef166
+Subproject commit 1d7d43603791e0236b56d076578657bee44fef6b
-Subproject commit b8e20d265b368dd6252703d5afd038d0b028e388
+Subproject commit d4433b0972f40cb3efaa3fbba52869bde5df8fa8
.I info
Print the architecture the AOT in this copy of Mono targets and quit.
.TP
+.I interp
+Generates all required wrappers, so that it is possible to run --interpreter without
+any code generation at runtime. This option only makes sense with \fBmscorlib.dll\fR.
+Embedders can set
+
+.nf
+mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP);
+.fi
+.ne
+.TP
.I ld-flags
Additional flags to pass to the C linker (if the current AOT mode calls for invoking it).
.TP
compile 10 methods with LLVM and then switch to the Mono JIT engine.
\fBLLVM_COUNT=0\fR would disable the LLVM engine altogether.
.TP
-\fBMONO_AOT_CACHE\fR
-If set, this variable will instruct Mono to ahead-of-time compile new
-assemblies on demand and store the result into a cache in
-~/.mono/aot-cache.
-.TP
\fBMONO_ASPNET_INHIBIT_SETTINGSMAP\fR
Mono contains a feature which allows modifying settings in the .config files shipped
with Mono by using config section mappers. The mappers and the mapping rules are
if (!Version.TryParse (field.GetValue (null) as string, out version))
return 4;
- if (version < new Version (4, 9))
+ Version min_mono_version;
+#if __MonoCS__
+ min_mono_version = new Version (5, 4);
+#else
+ min_mono_version = new Version (4, 9);
+#endif
+
+ if (version < min_mono_version)
return 5;
return 0;
ifndef NO_TEST
test_nunit_lib = nunitlite.dll
-xunit_core := xunit.core xunit.abstractions xunit.assert
+xunit_core := xunit.core xunit.abstractions xunit.assert Xunit.NetCore.Extensions
xunit_deps := System.Runtime
-xunit_class_deps := Xunit.NetCore.Extensions
+xunit_src := $(patsubst %,$(topdir)/../external/xunit-binaries/%,BenchmarkAttribute.cs BenchmarkDiscover.cs)
+xunit_class_deps :=
xunit_libs_ref = $(patsubst %,-r:$(topdir)/../external/xunit-binaries/%.dll,$(xunit_core))
xunit_libs_ref += $(patsubst %,-r:$(topdir)/class/lib/$(PROFILE)/Facades/%.dll,$(xunit_deps))
tests_CLEAN_FILES += $(topdir)/build/deps/nunit-$(PROFILE).stamp
-$(topdir)/class/lib/$(PROFILE)/$(PARENT_PROFILE)Xunit.NetCore.Extensions.dll:
- $(MAKE) -C $(topdir)/class/Xunit.NetCore.Extensions
-
endif
test_assemblies :=
$$ok
@rm -f xunit.execution.desktop.dll
-$(xunit_test_lib): $(the_assembly) $(xtest_response) $(xunit_libs_dep)
- $(TEST_COMPILE) $(LIBRARY_FLAGS) $(XTEST_LIB_FLAGS) -target:library -out:$@ $(xtest_flags) @$(xtest_response)
+$(xunit_test_lib): $(the_assembly) $(xtest_response) $(xunit_libs_dep) $(xunit_src)
+ $(TEST_COMPILE) $(LIBRARY_FLAGS) $(XTEST_LIB_FLAGS) -target:library -out:$@ $(xtest_flags) @$(xtest_response) $(xunit_src)
xtest_response_preprocessed = $(xtest_response)_preprocessed
<SchemaVersion>2.0</SchemaVersion>\r
<ProjectGuid>{71D02788-3AD8-4C43-BDEB-1A3D277496BA}</ProjectGuid>\r
<OutputType>Library</OutputType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
+ <NoWarn>1699,1616,1699,436</NoWarn>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Windows_NT'">win32</HostPlatform>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix' and $([System.IO.File]::Exists('/usr/lib/libc.dylib'))">darwin</HostPlatform>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix'">linux</HostPlatform>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
<DebugSymbols>true</DebugSymbols>\r
<DebugType>full</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
+ <NoWarn>1699,1616,1699,436</NoWarn>\r
<Optimize>false</Optimize>\r
<DefineConstants>TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
</PropertyGroup>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
<DebugType>pdbonly</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
+ <NoWarn>1699,1616,1699,436</NoWarn>\r
<Optimize>true</Optimize>\r
<DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Conversions.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\COperators.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Declarations\AggregateDeclaration.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Declarations\Declaration.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Declarations\GlobalAttributeDeclaration.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Declarations\NamespaceDeclaration.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\ExplicitConversion.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\ExpressionBinder.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\ExpressionKind.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\EventSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\FieldSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\IndexerSymbol.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\LabelSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\LocalVariableSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\MethodOrPropertySymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\MethodSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\SymbolTable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\SymFactory.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\SymFactoryBase.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\TransparentIdentifierMemberSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\TypeParameterSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\UnresolvedAggregateSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\VariableSymbol.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\ArrayIndex.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\ArrayInitialization.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\ArrayLength.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Assignment.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\BinaryOperator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Block.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Class.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\CompoundOperator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Concatenate.cs" />\r
- <Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\ConditionalOperator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Constant.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\Event.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Microsoft.CSharp\src\Microsoft\CSharp\RuntimeBinder\Semantics\Tree\EXPR.cs" />\r
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversions.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/COperators.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Declarations/AggregateDeclaration.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Declarations/Declaration.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Declarations/GlobalAttributeDeclaration.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Declarations/NamespaceDeclaration.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExplicitConversion.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionKind.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/EventSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/FieldSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/IndexerSymbol.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/LabelSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/LocalVariableSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolTable.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactory.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactoryBase.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/TransparentIdentifierMemberSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/TypeParameterSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/UnresolvedAggregateSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/VariableSymbol.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ArrayIndex.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ArrayInitialization.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ArrayLength.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Assignment.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/BinaryOperator.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Block.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Class.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/CompoundOperator.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Concatenate.cs
-../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ConditionalOperator.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Constant.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Event.cs
../../../external/corefx/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/EXPR.cs
return 42;
}
+ public int invoke_pass_nullable (int? i) {
+ return (int)i;
+ }
+
public int? invoke_return_nullable_null () {
return null;
}
+ public int invoke_pass_nullable_null (int? i) {
+ return i.HasValue ? 1 : 2;
+ }
+
public void invoke_type_load () {
new Class3 ();
}
m = s.Type.GetMethod ("ToString");
v = s.InvokeMethod (e.Thread, m, null);
+ // pass nullable as argument
+ m = t.GetMethod ("invoke_pass_nullable");
+ v = this_obj.InvokeMethod (e.Thread, m, new Value [] { s });
+ AssertValue (42, v);
+
// return nullable null
m = t.GetMethod ("invoke_return_nullable_null");
v = this_obj.InvokeMethod (e.Thread, m, null);
m = s.Type.GetMethod ("ToString");
v = s.InvokeMethod (e.Thread, m, null);
+ // pass nullable null as argument
+ m = t.GetMethod ("invoke_pass_nullable_null");
+ v = this_obj.InvokeMethod (e.Thread, m, new Value [] { s });
+ AssertValue (2, v);
+
+ return;
+
// pass primitive
m = t.GetMethod ("invoke_pass_primitive");
Value[] args = new Value [] {
e.Run = (args) => e.CommandSet.Out.WriteLine (string.Join (" ", args));
var o = new StringWriter ();
- var c = new CommandSet ("set", output:o) {
+ var c = new CommandSet ("set", output:o, error: Console.Error) {
e,
};
Assert.AreEqual (0, c.Run (new [] { "help", "echo" }));
c, v => { string ignore = v.OptionValues [0]; });
c.Option = p [0];
Utils.AssertException (typeof(ArgumentOutOfRangeException),
- "Specified argument was out of the range of valid values.\nParameter name: index",
+ $"Specified argument was out of the range of valid values.{Environment.NewLine}Parameter name: index",
c, v => { string ignore = v.OptionValues [2]; });
c.OptionName = "-a";
Utils.AssertException (typeof(OptionException),
p, v => { v.Parse (_("-a", "-b")); });
Assert.AreEqual (a, "-b");
Utils.AssertException (typeof(ArgumentNullException),
- "Value cannot be null.\nParameter name: option",
+ $"Value cannot be null.{Environment.NewLine}Parameter name: option",
p, v => { v.Add ((Option) null); });
Utils.AssertException (typeof(ArgumentNullException),
- "Value cannot be null.\nParameter name: header",
+ $"Value cannot be null.{Environment.NewLine}Parameter name: header",
p, v => { v.Add ((string) null); });
// bad type
p, v => { v.Parse (_("-cz", "extra")); });
Utils.AssertException (typeof(ArgumentNullException),
- "Value cannot be null.\nParameter name: action",
+ $"Value cannot be null.{Environment.NewLine}Parameter name: action",
p, v => { v.Add ("foo", (Action<string>) null); });
Utils.AssertException (typeof(ArgumentException),
- "Cannot provide maxValueCount of 2 for OptionValueType.None.\nParameter name: maxValueCount",
+ $"Cannot provide maxValueCount of 2 for OptionValueType.None.{Environment.NewLine}Parameter name: maxValueCount",
p, v => { v.Add ("foo", (k, val) => {/* ignore */}); });
}
Utils.AssertException (typeof(ArgumentException), "prototypes must be null!",
p, v => { v.Add ("N|NUM=", (int n) => {}); });
Utils.AssertException (typeof(ArgumentNullException),
- "Value cannot be null.\nParameter name: option",
+ $"Value cannot be null.{Environment.NewLine}Parameter name: option",
p, v => { v.GetOptionForName (null); });
}
{
object p = null;
Utils.AssertException (typeof(ArgumentNullException),
- "Value cannot be null.\nParameter name: prototype",
+ $"Value cannot be null.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption (null, null); });
Utils.AssertException (typeof(ArgumentException),
- "Cannot be the empty string.\nParameter name: prototype",
+ $"Cannot be the empty string.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("", null); });
Utils.AssertException (typeof(ArgumentException),
- "Empty option names are not supported.\nParameter name: prototype",
+ $"Empty option names are not supported.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("a|b||c=", null); });
Utils.AssertException (typeof(ArgumentException),
- "Conflicting option types: '=' vs. ':'.\nParameter name: prototype",
+ $"Conflicting option types: '=' vs. ':'.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("a=|b:", null); });
Utils.AssertException (typeof(ArgumentException),
- "The default option handler '<>' cannot require values.\nParameter name: prototype",
+ $"The default option handler '<>' cannot require values.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("<>=", null); });
Utils.AssertException (typeof(ArgumentException),
- "The default option handler '<>' cannot require values.\nParameter name: prototype",
+ $"The default option handler '<>' cannot require values.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("<>:", null); });
Utils.AssertException (null, null,
p, v => { new DefaultOption ("t|<>=", null, 1); });
Utils.AssertException (typeof(ArgumentException),
- "The default option handler '<>' cannot require values.\nParameter name: prototype",
+ $"The default option handler '<>' cannot require values.{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("t|<>=", null, 2); });
Utils.AssertException (null, null,
p, v => { new DefaultOption ("a|b=", null, 2); });
Utils.AssertException (typeof(ArgumentOutOfRangeException),
- "Specified argument was out of the range of valid values.\nParameter name: maxValueCount",
+ $"Specified argument was out of the range of valid values.{Environment.NewLine}Parameter name: maxValueCount",
p, v => { new DefaultOption ("a", null, -1); });
Utils.AssertException (typeof(ArgumentException),
"Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
- "OptionValueType.Optional.\nParameter name: maxValueCount",
+ $"OptionValueType.Optional.{Environment.NewLine}Parameter name: maxValueCount",
p, v => { new DefaultOption ("a=", null, 0); });
Utils.AssertException (typeof(ArgumentException),
- "Ill-formed name/value separator found in \"a={\".\nParameter name: prototype",
+ "Ill-formed name/value separator found in \"a={\"." + Environment.NewLine + "Parameter name: prototype",
p, v => { new DefaultOption ("a={", null); });
Utils.AssertException (typeof(ArgumentException),
- "Ill-formed name/value separator found in \"a=}\".\nParameter name: prototype",
+ "Ill-formed name/value separator found in \"a=}\"." + Environment.NewLine + "Parameter name: prototype",
p, v => { new DefaultOption ("a=}", null); });
Utils.AssertException (typeof(ArgumentException),
- "Ill-formed name/value separator found in \"a={{}}\".\nParameter name: prototype",
+ "Ill-formed name/value separator found in \"a={{}}\"." + Environment.NewLine + "Parameter name: prototype",
p, v => { new DefaultOption ("a={{}}", null); });
Utils.AssertException (typeof(ArgumentException),
- "Ill-formed name/value separator found in \"a={}}\".\nParameter name: prototype",
+ "Ill-formed name/value separator found in \"a={}}\"." + Environment.NewLine + "Parameter name: prototype",
p, v => { new DefaultOption ("a={}}", null); });
Utils.AssertException (typeof(ArgumentException),
- "Ill-formed name/value separator found in \"a={}{\".\nParameter name: prototype",
+ "Ill-formed name/value separator found in \"a={}{\"." + Environment.NewLine + "Parameter name: prototype",
p, v => { new DefaultOption ("a={}{", null); });
Utils.AssertException (typeof(ArgumentException),
- "Cannot provide key/value separators for Options taking 1 value(s).\nParameter name: prototype",
+ $"Cannot provide key/value separators for Options taking 1 value(s).{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("a==", null); });
Utils.AssertException (typeof(ArgumentException),
- "Cannot provide key/value separators for Options taking 1 value(s).\nParameter name: prototype",
+ $"Cannot provide key/value separators for Options taking 1 value(s).{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("a={}", null); });
Utils.AssertException (typeof(ArgumentException),
- "Cannot provide key/value separators for Options taking 1 value(s).\nParameter name: prototype",
+ $"Cannot provide key/value separators for Options taking 1 value(s).{Environment.NewLine}Parameter name: prototype",
p, v => { new DefaultOption ("a=+-*/", null); });
Utils.AssertException (null, null,
p, v => { new DefaultOption ("a", null, 0); });
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
}
+ unsafe {
+ fixed (char* p = s) {
+ fixed (byte* b = bytes) {
+ return GetBytes (p + charIndex, charCount, b + byteIndex, bytes.Length - byteIndex);
+ }
+ }
+ }
+ }
+
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException (bytes == null ? "bytes" : "chars");
+
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException (charCount < 0 ? "charCount" : "byteCount");
+
// Convert the characters into bytes.
char ch;
- int length = bytes.Length;
+ int length = byteCount;
uint pair;
- int posn = byteIndex;
+ int posn = 0;
+ int charIndex = 0;
while (charCount > 0) {
// Fetch the next UTF-16 character pair value.
- ch = s[charIndex++];
+ ch = chars [charIndex++];
if (ch >= '\uD800' && ch <= '\uDBFF' && charCount > 1) {
// This may be the start of a surrogate pair.
- pair = (uint)(s[charIndex]);
+ pair = (uint)(chars[charIndex]);
if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
pair = (pair - (uint)0xDC00) +
((((uint)ch) - (uint)0xD800) << 10) +
}
charCount -= 2;
if (charCount >= 0) {
- bytes[posn++] = (byte) s [charIndex++];
+ bytes[posn++] = (byte)chars [charIndex++];
}
continue;
} else {
}
// Return the final count to the caller.
- return posn - byteIndex;
+ return posn;
}
// Internal version of "GetCharCount" which can handle a rolling
uint leftSoFar = (leftOverCount & (uint)0x0F);
uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
while (count > 0) {
- ch = (uint)(bytes[index++]);
+ ch = (uint)(bytes [index++]);
++next_raw;
--count;
if (leftSize == 0) {
if (encoding == null)
throw new ArgumentNullException ("encoding");
- int min_byte_count = encoding.GetMaxByteCount(1);
- char[] copy = s.ToCharArray (index, count);
- byte[] marshal = new byte [encoding.GetByteCount (copy) + min_byte_count];
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException ((index < 0 ? "index" : "count"),
+ "Non - negative number required.");
- int bytes_copied = encoding.GetBytes (copy, 0, copy.Length, marshal, 0);
+ if (s.Length - index < count)
+ throw new ArgumentOutOfRangeException ("s", "Index and count must refer to a location within the string.");
- if (bytes_copied != (marshal.Length-min_byte_count))
- throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
+ int null_terminator_count = encoding.GetMaxByteCount (1);
+ int length_without_null = encoding.GetByteCount (s);
+ int marshalLength = checked (length_without_null + null_terminator_count);
- IntPtr mem = AllocHeap (marshal.Length);
+ IntPtr mem = AllocHeap (marshalLength);
if (mem == IntPtr.Zero)
throw new UnixIOException (Native.Errno.ENOMEM);
- bool copied = false;
- try {
- Marshal.Copy (marshal, 0, mem, marshal.Length);
- copied = true;
- }
- finally {
- if (!copied)
- FreeHeap (mem);
+ unsafe {
+ fixed (char* p = s) {
+ byte* marshal = (byte*)mem;
+ int bytes_copied;
+
+ try {
+ bytes_copied = encoding.GetBytes (p + index, count, marshal, marshalLength);
+ } catch {
+ FreeHeap (mem);
+ throw;
+ }
+
+ if (bytes_copied != length_without_null) {
+ FreeHeap (mem);
+ throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
+ }
+
+ marshal += length_without_null;
+ for (int i = 0; i < null_terminator_count; ++i)
+ marshal[i] = 0;
+ }
}
return mem;
void EndWrite (IAsyncResult asyncResult);
+ Task ShutdownAsync ();
+
TransportContext TransportContext {
get;
}
Mono.Security.Cryptography/RSAManagedTest.cs
Mono.Security.Cryptography/SHA224ManagedTest.cs
Mono.Security.Cryptography/SHA224Test.cs
+Mono.Security.Interface/TestProvider.cs
Mono.Security.Protocol.Ntlm/ChallengeResponseTest.cs
Mono.Security.Protocol.Ntlm/MessageBaseTest.cs
Mono.Security.Protocol.Ntlm/Type1MessageTest.cs
--- /dev/null
+//
+// TestProvider.cs
+//
+// Author:
+// Martin Baulig <mabaul@microsoft.com>
+//
+// Copyright (c) 2017 Xamarin, Inc.
+//
+// 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.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+using Mono.Security;
+using Mono.Security.Interface;
+using NUnit.Framework;
+
+namespace MonoTests.Mono.Security
+{
+ [TestFixture]
+ public class TestProvider
+ {
+ [Test]
+ public void GetProvider ()
+ {
+ var provider = MonoTlsProviderFactory.GetProvider ();
+ Assert.IsNotNull (provider, "TLS Provider");
+ }
+ }
+}
</PropertyGroup>\r
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
<ItemGroup>\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\BitmapSuffixInSameAssemblyAttribute.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\BitmapSuffixInSatelliteAssemblyAttribute.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\CategoryNameCollection.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\IPropertyValueUIService.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\IToolboxItemProvider.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\IToolboxService.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\IToolboxUser.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\PaintValueEventArgs.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\PropertyValueUIHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\PropertyValueUIItem.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\PropertyValueUIItemInvokeHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxComponentsCreatedEventArgs.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxComponentsCreatedEventHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxComponentsCreatingEventArgs.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxComponentsCreatingEventHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxItemCollection.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\ToolboxItemCreatorCallback.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\UITypeEditorEditStyle.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\IDeviceContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PreviewPageInfo.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrintAction.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterUnit.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrintEventHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrintingPermissionLevel.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrintPageEventHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\QueryPageSettingsEventArgs.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\QueryPageSettingsEventHandler.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\RotateFlipType.cs" />\r
<Compile Include="..\..\build\common\Consts.cs" />\r
<Compile Include="..\..\build\common\Locale.cs" />\r
<Compile Include="..\..\build\common\MonoTODOAttribute.cs" />\r
<Compile Include="Assembly\AssemblyInfo.cs" />\r
- <Compile Include="System.Drawing.Design\CategoryNameCollection.cs" />\r
- <Compile Include="System.Drawing.Design\IPropertyValueUIService.cs" />\r
- <Compile Include="System.Drawing.Design\IToolboxItemProvider.cs" />\r
- <Compile Include="System.Drawing.Design\IToolboxService.cs" />\r
- <Compile Include="System.Drawing.Design\IToolboxUser.cs" />\r
- <Compile Include="System.Drawing.Design\PaintValueEventArgs.cs" />\r
- <Compile Include="System.Drawing.Design\PropertyValueItem.cs" />\r
- <Compile Include="System.Drawing.Design\PropertyValueUIHandler.cs" />\r
- <Compile Include="System.Drawing.Design\PropertyValueUIItemInvokeHandler.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxComponentsCreatedEventArgs.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxComponentsCreatedEventHandler.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxComponentsCreatingEventArgs.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxComponentsCreatingEventHandler.cs" />\r
<Compile Include="System.Drawing.Design\ToolboxItem.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxItemCollection.cs" />\r
- <Compile Include="System.Drawing.Design\ToolboxItemCreatorCallback.cs" />\r
<Compile Include="System.Drawing.Design\UITypeEditor.cs" />\r
- <Compile Include="System.Drawing.Design\UITypeEditorEditStyle.cs" />\r
<Compile Include="System.Drawing.Drawing2D\AdjustableArrowCap.cs" />\r
<Compile Include="System.Drawing.Drawing2D\Blend.cs" />\r
<Compile Include="System.Drawing.Drawing2D\ColorBlend.cs" />\r
<Compile Include="System.Drawing.Printing\PaperSize.cs" />\r
<Compile Include="System.Drawing.Printing\PaperSource.cs" />\r
<Compile Include="System.Drawing.Printing\PaperSourceKind.cs" />\r
- <Compile Include="System.Drawing.Printing\PreviewPageInfo.cs" />\r
<Compile Include="System.Drawing.Printing\PreviewPrintController.cs" />\r
- <Compile Include="System.Drawing.Printing\PrintAction.cs" />\r
<Compile Include="System.Drawing.Printing\PrintController.cs" />\r
<Compile Include="System.Drawing.Printing\PrintDocument.cs" />\r
<Compile Include="System.Drawing.Printing\PrinterResolution.cs" />\r
<Compile Include="System.Drawing.Printing\PrinterResolutionKind.cs" />\r
<Compile Include="System.Drawing.Printing\PrinterSettings.cs" />\r
- <Compile Include="System.Drawing.Printing\PrinterUnit.cs" />\r
<Compile Include="System.Drawing.Printing\PrinterUnitConvert.cs" />\r
<Compile Include="System.Drawing.Printing\PrintEventArgs.cs" />\r
- <Compile Include="System.Drawing.Printing\PrintEventHandler.cs" />\r
<Compile Include="System.Drawing.Printing\PrintingPermission.cs" />\r
<Compile Include="System.Drawing.Printing\PrintingPermissionAttribute.cs" />\r
- <Compile Include="System.Drawing.Printing\PrintingPermissionLevel.cs" />\r
<Compile Include="System.Drawing.Printing\PrintingServices.cs" />\r
<Compile Include="System.Drawing.Printing\PrintingServicesUnix.cs" />\r
<Compile Include="System.Drawing.Printing\PrintingServicesWin32.cs" />\r
<Compile Include="System.Drawing.Printing\PrintPageEventArgs.cs" />\r
- <Compile Include="System.Drawing.Printing\PrintPageEventHandler.cs" />\r
<Compile Include="System.Drawing.Printing\PrintRange.cs" />\r
- <Compile Include="System.Drawing.Printing\QueryPageSettingsEventArgs.cs" />\r
- <Compile Include="System.Drawing.Printing\QueryPageSettingsEventHandler.cs" />\r
<Compile Include="System.Drawing.Printing\StandardPrintController.cs" />\r
<Compile Include="System.Drawing.Text\FontCollection.cs" />\r
<Compile Include="System.Drawing.Text\GenericFontFamilies.cs" />\r
<Compile Include="System.Drawing.Text\PrivateFontCollection.cs" />\r
<Compile Include="System.Drawing.Text\TextRenderingHint.cs" />\r
<Compile Include="System.Drawing\Bitmap.cs" />\r
- <Compile Include="System.Drawing\BitmapSuffixInSameAssemblyAttribute.cs" />\r
- <Compile Include="System.Drawing\BitmapSuffixInSatelliteAssemblyAttribute.cs" />\r
<Compile Include="System.Drawing\Brush.cs" />\r
<Compile Include="System.Drawing\Brushes.cs" />\r
<Compile Include="System.Drawing\BufferedGraphics.cs" />\r
<Compile Include="System.Drawing\GraphicsUnit.cs" />\r
<Compile Include="System.Drawing\Icon.cs" />\r
<Compile Include="System.Drawing\IconConverter.cs" />\r
- <Compile Include="System.Drawing\IDeviceContext.cs" />\r
<Compile Include="System.Drawing\Image.cs" />\r
<Compile Include="System.Drawing\ImageAnimator.cs" />\r
<Compile Include="System.Drawing\ImageConverter.cs" />\r
<Compile Include="System.Drawing\RectangleConverter.cs" />\r
<Compile Include="System.Drawing\RectangleF.cs" />\r
<Compile Include="System.Drawing\Region.cs" />\r
- <Compile Include="System.Drawing\RotateFlipType.cs" />\r
<Compile Include="System.Drawing\Size.cs" />\r
<Compile Include="System.Drawing\SizeConverter.cs" />\r
<Compile Include="System.Drawing\SizeF.cs" />\r
+++ /dev/null
-//
-// System.Drawing.Design.CategoryNameCollection.cs
-//
-// Authors:
-// Alejandro Sánchez Acosta
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) Alejandro Sánchez Acosta
-// (C) 2003 Andreas Nahr
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.Collections;
-
-namespace System.Drawing.Design
-{
- public sealed class CategoryNameCollection : ReadOnlyCollectionBase
- {
-
- public CategoryNameCollection (CategoryNameCollection value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- InnerList.AddRange (value);
- }
-
- public CategoryNameCollection (string[] value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- InnerList.AddRange (value);
- }
-
- public string this[int index] {
- get {
- return (string) InnerList[index];
- }
- }
-
- public bool Contains (string value)
- {
- return InnerList.Contains (value);
- }
-
- public void CopyTo (string[] array, int index)
- {
- InnerList.CopyTo (array, index);
- }
-
- public int IndexOf (string value)
- {
- return InnerList.IndexOf (value);
- }
- }
-}
+++ /dev/null
-// System.Drawing.Design.IPropertyValueUIService.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.Drawing;
-using System.ComponentModel;
-
-namespace System.Drawing.Design
-{
- public interface IPropertyValueUIService
- {
-
- #region Methods
- void AddPropertyValueUIHandler (PropertyValueUIHandler newHandler);
- PropertyValueUIItem[] GetPropertyUIValueItems (ITypeDescriptorContext context, PropertyDescriptor propDesc);
-
- void NotifyPropertyValueUIItemsChanged ();
-
- void RemovePropertyValueUIHandler (PropertyValueUIHandler newHandler);
- #endregion Methods
-
- #region Events
- event EventHandler PropertyUIValueItemsChanged;
- #endregion Events
- }
-}
-
+++ /dev/null
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.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.
-//
-// Authors:
-//
-// Jordi Mas i Hernandez <jordimash@gmail.com>
-//
-//
-
-
-namespace System.Drawing.Design
-{
- public interface IToolboxItemProvider
- {
- ToolboxItemCollection Items { get; }
- }
-}
-
-
+++ /dev/null
-//
-// System.Drawing.Design.IToolboxService.cs
-//
-// Authors:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) Alejandro Sánchez Acosta
-// (C) 2003 Andreas Nahr
-// Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.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.Collections;
-using System.ComponentModel.Design;
-using System.Runtime.InteropServices;
-
-namespace System.Drawing.Design {
-
- [ComImport]
- [Guid("4BACD258-DE64-4048-BC4E-FEDBEF9ACB76"),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IToolboxService
- {
- CategoryNameCollection CategoryNames {get;}
-
- string SelectedCategory {get; set;}
-
- void AddCreator (ToolboxItemCreatorCallback creator, string format);
-
- void AddCreator (ToolboxItemCreatorCallback creator, string format, IDesignerHost host);
-
- void AddLinkedToolboxItem (ToolboxItem toolboxItem, IDesignerHost host);
-
- void AddLinkedToolboxItem (ToolboxItem toolboxItem, string category, IDesignerHost host);
-
- void AddToolboxItem (ToolboxItem toolboxItem, String category);
-
- void AddToolboxItem (ToolboxItem toolboxItem);
-
- ToolboxItem DeserializeToolboxItem (object serializedObject);
-
- ToolboxItem DeserializeToolboxItem (object serializedObject, IDesignerHost host);
-
- ToolboxItem GetSelectedToolboxItem ();
-
- ToolboxItem GetSelectedToolboxItem (IDesignerHost host);
-
- ToolboxItemCollection GetToolboxItems ();
-
- ToolboxItemCollection GetToolboxItems (IDesignerHost host);
-
- ToolboxItemCollection GetToolboxItems (String category);
-
- ToolboxItemCollection GetToolboxItems (String category, IDesignerHost host);
-
- bool IsSupported (object serializedObject, ICollection filterAttributes);
-
- bool IsSupported (object serializedObject, IDesignerHost host);
-
- bool IsToolboxItem (object serializedObject);
-
- bool IsToolboxItem (object serializedObject, IDesignerHost host);
-
- void Refresh();
-
- void RemoveCreator (string format);
-
- void RemoveCreator (string format, IDesignerHost host);
-
- void RemoveToolboxItem (ToolboxItem toolboxItem);
-
- void RemoveToolboxItem (ToolboxItem toolboxItem, string category);
-
- void SelectedToolboxItemUsed ();
-
- object SerializeToolboxItem (ToolboxItem toolboxItem);
-
- bool SetCursor ();
-
- void SetSelectedToolboxItem (ToolboxItem toolboxItem);
- }
-}
+++ /dev/null
-// System.Drawing.Design.IToolboxUser.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Design
-{
- public interface IToolboxUser
- {
- bool GetToolSupported (ToolboxItem tool);
-
- void ToolPicked (ToolboxItem tool);
- }
-}
+++ /dev/null
-// System.Drawing.Design.PaintvalueEventArgs.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.ComponentModel;
-
-namespace System.Drawing.Design
-{
- public class PaintValueEventArgs : EventArgs
- {
- private ITypeDescriptorContext context;
- private object value;
- private Graphics graphics;
- private Rectangle bounds;
-
- public PaintValueEventArgs(ITypeDescriptorContext context, object value, Graphics graphics, Rectangle bounds)
- {
- if (graphics == null)
- throw new ArgumentNullException ("graphics");
- this.context = context;
- this.value = value;
- this.graphics = graphics;
- this.bounds = bounds;
- }
-
- public Rectangle Bounds
- {
- get {
- return bounds;
- }
- }
-
- public ITypeDescriptorContext Context
- {
- get {
- return context;
- }
- }
-
- public Graphics Graphics
- {
- get {
- return graphics;
- }
- }
-
- public object Value
- {
- get {
- return value;
- }
- }
- }
-}
-
+++ /dev/null
-//
-// System.Drawing.Design.PropertyValueItem.cs
-//
-// Authors:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) Alejandro Sánchez Acosta
-// (C) 2003 Andreas Nahr
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Design
-{
- public class PropertyValueUIItem
- {
-
- private Image uiItemImage;
- private PropertyValueUIItemInvokeHandler handler;
- private string tooltip;
-
- public PropertyValueUIItem (Image uiItemImage,
- PropertyValueUIItemInvokeHandler handler, string tooltip)
- {
- if (uiItemImage == null)
- throw new ArgumentNullException ("uiItemImage");
- if (handler == null)
- throw new ArgumentNullException ("handler");
- this.uiItemImage = uiItemImage;
- this.handler = handler;
- this.tooltip = tooltip;
- }
-
- public virtual Image Image
- {
- get
- {
- return uiItemImage;
- }
- }
-
- public virtual PropertyValueUIItemInvokeHandler InvokeHandler
- {
- get
- {
- return handler;
- }
- }
-
- public virtual string ToolTip
- {
- get
- {
- return tooltip;
- }
- }
-
- public virtual void Reset()
- {
- // To be overriden in child classes
- }
- }
-}
+++ /dev/null
-// System.Drawing.Design.PropertyValueUIHandler.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.Collections;
-using System.ComponentModel;
-
-namespace System.Drawing.Design {
-
- public delegate void PropertyValueUIHandler (ITypeDescriptorContext context, PropertyDescriptor propDesc, ArrayList valueUIItemList);
-}
+++ /dev/null
-// System.Drawing.Design.PropertyValueUIItemInvokeHandler.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.ComponentModel;
-
-namespace System.Drawing.Design {
-
- public delegate void PropertyValueUIItemInvokeHandler (
- ITypeDescriptorContext context,
- PropertyDescriptor descriptor,
- PropertyValueUIItem invokedItem);
-}
+++ /dev/null
-// System.Drawing.Design.ToolboxComponentsCreatedEventArgs.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-//
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.ComponentModel;
-
-namespace System.Drawing.Design
-{
- public class ToolboxComponentsCreatedEventArgs : EventArgs
- {
- private IComponent[] components;
-
- public ToolboxComponentsCreatedEventArgs (IComponent[] components) {
- this.components = components;
- }
-
- public IComponent[] Components {
- get {
- return components;
- }
- }
- }
-}
+++ /dev/null
-// System.Drawing.Design.IDesignerHost.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Design {
-
- public delegate void ToolboxComponentsCreatedEventHandler (object sender, ToolboxComponentsCreatedEventArgs e);
-}
-
+++ /dev/null
-//
-// System.Drawing.Design.ToolboxComponentsCreatingEventArgs.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.ComponentModel.Design;
-using System.Security.Permissions;
-
-namespace System.Drawing.Design
-{
- [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
- [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
- public class ToolboxComponentsCreatingEventArgs : EventArgs
- {
- private IDesignerHost host;
-
- public ToolboxComponentsCreatingEventArgs (IDesignerHost host)
- {
- this.host = host;
- }
-
- public IDesignerHost DesignerHost {
- get {
- return host;
- }
- }
- }
-}
-
-
+++ /dev/null
-// System.Drawing.Design.ToolboxComponentsCreatingEventHandler.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Design {
-
- public delegate void ToolboxComponentsCreatingEventHandler (object sender, ToolboxComponentsCreatingEventArgs e);
-}
+++ /dev/null
-//
-// System.Drawing.Design.ToolboxItemCollection.cs
-//
-// Authors:
-// Martin Willemoes Hansen (mwh@sysrq.dk)
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) 2003 Martin Willemoes Hansen
-// (C) 2003 Andreas Nahr
-//
-
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.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.Collections;
-using System.Security.Permissions;
-
-namespace System.Drawing.Design
-{
- [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
- public sealed class ToolboxItemCollection : ReadOnlyCollectionBase
- {
-
- public ToolboxItemCollection (ToolboxItem[] value) : base()
- {
- InnerList.AddRange (value);
- }
-
- public ToolboxItemCollection (ToolboxItemCollection value) : base()
- {
- InnerList.AddRange (value);
- }
-
- public ToolboxItem this [int index] {
- get { return (ToolboxItem) InnerList[index]; }
- }
-
- public bool Contains (ToolboxItem value)
- {
- return InnerList.Contains (value);
- }
-
- public void CopyTo (ToolboxItem[] array, int index)
- {
- InnerList.CopyTo (array, index);
- }
-
- public int IndexOf (ToolboxItem value)
- {
- return InnerList.IndexOf (value);
- }
- }
-}
+++ /dev/null
-// System.Drawing.Design.ToolboxItemCreatorCallback.cs
-//
-// Author:
-// Alejandro Sánchez Acosta <raciel@es.gnu.org>
-//
-// (C) Alejandro Sánchez Acosta
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Design {
-
- public delegate ToolboxItem ToolboxItemCreatorCallback(
- object serializedObject,
- string format);
-}
+++ /dev/null
-//
-// System.Drawing.Design.UITypeEditorEditStyle.cs
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Author: Dennis Hayes (dennish@raytek.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-namespace System.Drawing.Design
-{
- public enum UITypeEditorEditStyle{
- DropDown=3,
- Modal=2,
- None=1
- }
-}
\ No newline at end of file
+++ /dev/null
-//
-// System.Drawing.PreviewPageInfo.cs
-//
-// Author:
-// Dennis Hayes (dennish@Raytek.com)
-//
-// (C) 2002 Ximian, Inc
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Drawing.Printing
-{
- /// <summary>
- /// Summary description for PreviewPageInfo.
- /// </summary>
- public sealed class PreviewPageInfo {
- Image image;
- Size physicalSize;
- public PreviewPageInfo(Image image, Size physicalSize) {
- this.image = image;
- this.physicalSize = physicalSize;
- }
- public Image Image {
- get{
- return image;
- }
- }
- public Size PhysicalSize{
- get{
- return physicalSize;
- }
- }
- }
-}
+++ /dev/null
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.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.
-//
-// Authors:
-//
-// Jordi Mas i Hernandez <jordimash@gmail.com>
-//
-//
-
-
-using System;
-
-namespace System.Drawing.Printing
-{
- public enum PrintAction
- {
- PrintToFile = 0,
- PrintToPreview = 1,
- PrintToPrinter = 2
- }
-
-}
-
-
+++ /dev/null
-//
-// System.Drawing.PrintEventHandler.cs
-//
-// Author:
-// Dennis Hayes (dennish@Raytek.com)
-//
-// (C) 2002 Ximian, Inc
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Drawing.Printing
-{
- /// <summary>
- /// Summary description for PrintEventHandler.
- /// </summary>
- public delegate void PrintEventHandler(object sender, PrintEventArgs e);
-}
+++ /dev/null
-//\r
-// System.Drawing.PrintPageEventHandler.cs\r
-//\r
-// Author:\r
-// Dennis Hayes (dennish@Raytek.com)\r
-//\r
-// (C) 2002 Ximian, Inc\r
-//\r
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;\r
-\r
-namespace System.Drawing.Printing\r
-{\r
- /// <summary>\r
- /// Summary description for PrintPageEventHandler.\r
- /// </summary>\r
- public delegate void PrintPageEventHandler(object sender, PrintPageEventArgs e);\r
-}\r
+++ /dev/null
-//\r
-// System.Drawing.PrinterUnit.cs\r
-//\r
-// (C) 2002 Ximian, Inc. http://www.ximian.com\r
-// Author: Dennis Hayes (dennish@raytek.com)\r
-//\r
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;\r
-namespace System.Drawing.Printing \r
-{\r
- public enum PrinterUnit {\r
- Display = 0,\r
- HundredthsOfAMillimeter = 2,\r
- TenthsOfAMillimeter = 3,\r
- ThousandthsOfAnInch = 1\r
- }\r
-}\r
+++ /dev/null
-//\r
-// System.Drawing.PrintingPermissionLevel.cs\r
-//\r
-// Author:
-// Dennis Hayes (dennish@raytek.com)\r
-//
-// (C) 2002 Ximian, Inc. http://www.ximian.com\r
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing.Printing {
-
- [Serializable]
- public enum PrintingPermissionLevel {\r
- AllPrinting = 3,\r
- DefaultPrinting = 2,\r
- NoPrinting = 0,\r
- SafePrinting = 1\r
- }\r
-}\r
+++ /dev/null
-//\r
-// System.Drawing.QueryPageSettingsEventArgs.cs\r
-//\r
-// Author:\r
-// Dennis Hayes (dennish@Raytek.com)\r
-//\r
-// (C) 2002 Ximian, Inc\r
-//\r
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;\r
-\r
-namespace System.Drawing.Printing\r
-{\r
- /// <summary>\r
- /// Summary description for QueryPageSettingEventArgs.\r
- /// </summary>\r
- public class QueryPageSettingsEventArgs : PrintEventArgs\r
- {\r
- private PageSettings pageSettings;\r
-\r
- public QueryPageSettingsEventArgs(PageSettings pageSettings)\r
- {\r
- this.pageSettings = pageSettings;\r
- }\r
- public PageSettings PageSettings {\r
- get{\r
- return pageSettings;\r
- }\r
- set{\r
- pageSettings = value;\r
- }\r
- }\r
-\r
- }\r
-}\r
+++ /dev/null
-//
-// System.Drawing.QueryPageSettingsEventHandler.cs
-//
-// Author:
-// Dennis Hayes (dennish@Raytek.com)
-//
-// (C) 2002 Ximian, Inc
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Drawing.Printing
-{
- /// <summary>
- /// Summary description for QueryPageSettingsEventHandler.
- /// </summary>
- public delegate void QueryPageSettingsEventHandler(object sender, QueryPageSettingsEventArgs e);
-}
../../build/common/Consts.cs
../../build/common/Locale.cs
System.Drawing/Bitmap.cs
-System.Drawing/BitmapSuffixInSameAssemblyAttribute.cs
-System.Drawing/BitmapSuffixInSatelliteAssemblyAttribute.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/BitmapSuffixInSameAssemblyAttribute.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/BitmapSuffixInSatelliteAssemblyAttribute.cs
System.Drawing/Brush.cs
System.Drawing/Brushes.cs
System.Drawing/BufferedGraphics.cs
System.Drawing/KnownColors.cs
System.Drawing/IconConverter.cs
System.Drawing/Icon.cs
-System.Drawing/IDeviceContext.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/IDeviceContext.cs
System.Drawing/ImageAnimator.cs
System.Drawing/ImageConverter.cs
System.Drawing/Image.cs
System.Drawing/Rectangle.cs
System.Drawing/RectangleF.cs
System.Drawing/Region.cs
-System.Drawing/RotateFlipType.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/RotateFlipType.cs
System.Drawing/SizeConverter.cs
System.Drawing/Size.cs
System.Drawing/SizeF.cs
System.Drawing/SystemPens.cs
System.Drawing/TextureBrush.cs
System.Drawing/ToolboxBitmapAttribute.cs
-System.Drawing.Design/UITypeEditorEditStyle.cs
-System.Drawing.Design/IPropertyValueUIService.cs
-System.Drawing.Design/IToolboxItemProvider.cs
-System.Drawing.Design/PropertyValueItem.cs
-System.Drawing.Design/PropertyValueUIHandler.cs
-System.Drawing.Design/PropertyValueUIItemInvokeHandler.cs
-System.Drawing.Design/CategoryNameCollection.cs
-System.Drawing.Design/IToolboxService.cs
-System.Drawing.Design/IToolboxUser.cs
-System.Drawing.Design/PaintValueEventArgs.cs
-System.Drawing.Design/ToolboxComponentsCreatedEventArgs.cs
-System.Drawing.Design/ToolboxComponentsCreatedEventHandler.cs
-System.Drawing.Design/ToolboxComponentsCreatingEventArgs.cs
-System.Drawing.Design/ToolboxComponentsCreatingEventHandler.cs
-System.Drawing.Design/ToolboxItemCreatorCallback.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/UITypeEditorEditStyle.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/IPropertyValueUIService.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/IToolboxItemProvider.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/PropertyValueUIItem.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/PropertyValueUIHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/PropertyValueUIItemInvokeHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/CategoryNameCollection.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/IToolboxService.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/IToolboxUser.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/PaintValueEventArgs.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxComponentsCreatedEventArgs.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxComponentsCreatedEventHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxComponentsCreatingEventArgs.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxComponentsCreatingEventHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxItemCreatorCallback.cs
System.Drawing.Design/ToolboxItem.cs
System.Drawing.Design/UITypeEditor.cs
-System.Drawing.Design/ToolboxItemCollection.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxItemCollection.cs
System.Drawing.Drawing2D/AdjustableArrowCap.cs
System.Drawing.Drawing2D/Blend.cs
System.Drawing.Drawing2D/ColorBlend.cs
System.Drawing.Printing/PaperSize.cs
System.Drawing.Printing/PaperSource.cs
System.Drawing.Printing/PaperSourceKind.cs
-System.Drawing.Printing/PreviewPageInfo.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PreviewPageInfo.cs
System.Drawing.Printing/PreviewPrintController.cs
System.Drawing.Printing/PrintController.cs
System.Drawing.Printing/PrintDocument.cs
System.Drawing.Printing/PrinterResolution.cs
System.Drawing.Printing/PrinterResolutionKind.cs
System.Drawing.Printing/PrinterSettings.cs
-System.Drawing.Printing/PrinterUnit.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrinterUnit.cs
System.Drawing.Printing/PrinterUnitConvert.cs
System.Drawing.Printing/PrintEventArgs.cs
-System.Drawing.Printing/PrintEventHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrintEventHandler.cs
System.Drawing.Printing/PrintingPermissionAttribute.cs
System.Drawing.Printing/PrintingPermission.cs
-System.Drawing.Printing/PrintingPermissionLevel.cs
-System.Drawing.Printing/PrintAction.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrintingPermissionLevel.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrintAction.cs
System.Drawing.Printing/PrintPageEventArgs.cs
-System.Drawing.Printing/PrintPageEventHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrintPageEventHandler.cs
System.Drawing.Printing/PrintRange.cs
-System.Drawing.Printing/QueryPageSettingsEventArgs.cs
-System.Drawing.Printing/QueryPageSettingsEventHandler.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/QueryPageSettingsEventArgs.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/QueryPageSettingsEventHandler.cs
System.Drawing.Printing/StandardPrintController.cs
System.Drawing.Text/FontCollection.cs
System.Drawing.Text/PrivateFontCollection.cs
+++ /dev/null
-//
-// System.Drawing.BitmapSuffixInSameAssemblyAttribute.cs
-//
-// Authors:
-// Andrés G. Aragoneses (knocte@gmail.com)
-//
-// Copyright (C) 2016 Andrés G. Aragoneses
-//
-// 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.ComponentModel;
-
-namespace System.Drawing
-{
- [AttributeUsage (AttributeTargets.Assembly)]
- public class BitmapSuffixInSameAssemblyAttribute : Attribute {
-
- public BitmapSuffixInSameAssemblyAttribute ()
- : base ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.Drawing.BitmapSuffixInSatelliteAssemblyAttribute.cs
-//
-// Authors:
-// Andrés G. Aragoneses (knocte@gmail.com)
-//
-// Copyright (C) 2016 Andrés G. Aragoneses
-//
-// 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.ComponentModel;
-
-namespace System.Drawing
-{
- [AttributeUsage (AttributeTargets.Assembly)]
- public class BitmapSuffixInSatelliteAssemblyAttribute : Attribute {
-
- public BitmapSuffixInSatelliteAssemblyAttribute ()
- : base ()
- {
- }
- }
-}
+++ /dev/null
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.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.
-//
-// Authors:
-//
-// Jordi Mas i Hernandez <jordimash@gmail.com>
-//
-//
-
-
-using System.ComponentModel;
-
-namespace System.Drawing
-{
- public interface IDeviceContext : IDisposable
- {
- IntPtr GetHdc ();
- void ReleaseHdc ();
- }
-}
-
-
//
// Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2013 Kristof Ralovich, changes are available under the terms of the MIT X11 license
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
public void SetPropertyItem(PropertyItem propitem)
{
- throw new NotImplementedException ();
-/*
- GdipPropertyItem pi = new GdipPropertyItem ();
- GdipPropertyItem.MarshalTo (pi, propitem);
- unsafe {
- Status status = GDIPlus.GdipSetPropertyItem (nativeObject, &pi);
+ if (propitem == null)
+ throw new ArgumentNullException ("propitem");
+
+ int nItemSize = Marshal.SizeOf (propitem.Value[0]);
+ int size = nItemSize * propitem.Value.Length;
+ IntPtr dest = Marshal.AllocHGlobal (size);
+ try {
+ GdipPropertyItem pi = new GdipPropertyItem ();
+ pi.id = propitem.Id;
+ pi.len = propitem.Len;
+ pi.type = propitem.Type;
+
+ Marshal.Copy (propitem.Value, 0, dest, size);
+ pi.value = dest;
+
+ unsafe {
+ Status status = GDIPlus.GdipSetPropertyItem (nativeObject, &pi);
- GDIPlus.CheckStatus (status);
+ GDIPlus.CheckStatus (status);
+ }
+ }
+ finally {
+ Marshal.FreeHGlobal (dest);
}
-*/
}
// properties
+++ /dev/null
-//
-// System.Drawing.RotateFlipType .cs
-//
-// Author: Dennis Hayes (dennish@raytek.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Drawing {
-
- public enum RotateFlipType {
- RotateNoneFlipNone = 0,
- Rotate180FlipXY = 0,
- Rotate90FlipNone = 1,
- Rotate270FlipXY = 1,
- Rotate180FlipNone = 2,
- RotateNoneFlipXY = 2,
- Rotate270FlipNone = 3,
- Rotate90FlipXY = 3,
- RotateNoneFlipX = 4,
- Rotate180FlipY = 4,
- Rotate90FlipX = 5,
- Rotate270FlipY = 5,
- Rotate180FlipX = 6,
- RotateNoneFlipY = 6,
- Rotate270FlipX = 7,
- Rotate90FlipY = 7,
- }
-}
+../../../external/corefx/src/Common/tests/System/AssertExtensions.cs
../../../external/corefx/src/Common/tests/System/PlatformDetection.cs
# ../../../external/corefx/src/System.Runtime.Numerics/tests/*.cs
{
string fullPath = (string) hostInitConfigurationParams [1];
map = (WebConfigurationFileMap) hostInitConfigurationParams [0];
- bool inAnotherApp = (bool) hostInitConfigurationParams [7];
+ bool inAnotherApp = false;
+
+ if ((hostInitConfigurationParams.Length > 7)
+ && (hostInitConfigurationParams[7] is bool))
+ inAnotherApp = (bool) hostInitConfigurationParams[7];
if (inAnotherApp)
appVirtualPath = fullPath;
*/
var certificate2 = certificate as X509Certificate2;
if (certificate2 != null)
+#if MONOTOUCH
+ return SecIdentity.Import (certificate2);
+#else
return SecImportExport.ItemImport (certificate2);
+#endif
/*
* Reading Certificates from the Mac Keychain
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ SslStatus SSLClose (/* SSLContextRef */ IntPtr context);
- public override void Close ()
+ public override void Shutdown ()
{
if (Interlocked.Exchange (ref pendingIO, 1) == 1)
throw new InvalidOperationException ();
- Debug ("Close");
+ Debug ("Shutdown");
lastException = null;
return;
var status = SSLClose (Handle);
- Debug ("Close done: {0}", status);
+ Debug ("Shutdown done: {0}", status);
CheckStatusAndThrow (status);
} finally {
closed = true;
}
protected override MNS.MobileTlsContext CreateContext (
- MNS.MobileAuthenticatedStream parent, bool serverMode, string targetHost,
- SslProtocols enabledProtocols, X509Certificate serverCertificate,
- X509CertificateCollection clientCertificates, bool askForClientCert)
+ bool serverMode, string targetHost, SslProtocols enabledProtocols,
+ X509Certificate serverCertificate, X509CertificateCollection clientCertificates,
+ bool askForClientCert)
{
return new AppleTlsContext (
- parent, serverMode, targetHost,
+ this, serverMode, targetHost,
enabledProtocols, serverCertificate,
clientCertificates, askForClientCert);
}
return code;
}
+#if !MONOTOUCH
[DllImport (AppleTlsContext.SecurityLibrary)]
extern static SecStatusCode SecItemImport (
/* CFDataRef */ IntPtr importedData,
IntPtr keyUsage;
IntPtr keyAttributes;
}
+#endif
}
}
#endif
if (status == MonoBtlsSslError.WantRead) {
wantMore = true;
return 0;
+ } else if (status == MonoBtlsSslError.ZeroReturn) {
+ wantMore = false;
+ return size;
} else if (status != MonoBtlsSslError.None) {
throw GetException (status);
}
}
}
- public override void Close ()
+ public override void Shutdown ()
{
- Debug ("Close!");
-
- if (ssl != null) {
- ssl.Dispose ();
- ssl = null;
- }
- if (ctx != null) {
- ctx.Dispose ();
- ctx = null;
- }
- if (bio != null) {
- bio.Dispose ();
- bio = null;
- }
- if (errbio != null) {
- errbio.Dispose ();
- errbio = null;
- }
+ Debug ("Shutdown!");
+// ssl.SetQuietShutdown ();
+ ssl.Shutdown ();
}
void Dispose<T> (ref T disposable)
{
try {
if (disposing) {
+ Dispose (ref ssl);
+ Dispose (ref ctx);
Dispose (ref remoteCertificate);
Dispose (ref nativeServerCertificate);
Dispose (ref nativeClientCertificate);
Dispose (ref clientCertificate);
- Dispose (ref ctx);
- Dispose (ref ssl);
Dispose (ref bio);
Dispose (ref errbio);
}
CheckError (ret == 1, callerName);
}
+ protected internal void CheckLastError ([CallerMemberName] string callerName = null)
+ {
+ var error = Interlocked.Exchange (ref lastError, null);
+ if (error == null)
+ return;
+
+ string message;
+ if (callerName != null)
+ message = string.Format ("Caught unhandled exception in {0}.{1}.", GetType ().Name, callerName);
+ else
+ message = string.Format ("Caught unhandled exception.");
+ throw new MonoBtlsException (message, error);
+ }
+
[DllImport (BTLS_DYLIB)]
extern static void mono_btls_free (IntPtr data);
protected override bool ReleaseHandle ()
{
mono_btls_ssl_destroy (handle);
+ handle = IntPtr.Zero;
return true;
}
}
[DllImport (BTLS_DYLIB)]
extern static void mono_btls_ssl_close (IntPtr handle);
+ [DllImport (BTLS_DYLIB)]
+ extern static int mono_btls_ssl_shutdown (IntPtr handle);
+
+ [DllImport (BTLS_DYLIB)]
+ extern static void mono_btls_ssl_set_quiet_shutdown (IntPtr handle, int mode);
+
[DllImport (BTLS_DYLIB)]
extern static void mono_btls_ssl_set_bio (IntPtr handle, IntPtr bio);
return new BoringSslHandle (handle);
}
+ MonoBtlsBio bio;
PrintErrorsCallbackFunc printErrorsFunc;
IntPtr printErrorsFuncPtr;
public void SetBio (MonoBtlsBio bio)
{
CheckThrow ();
+ this.bio = bio;
mono_btls_ssl_set_bio (
Handle.DangerousGetHandle (),
bio.Handle.DangerousGetHandle ());
errors = null;
}
- if (errors != null) {
- Console.Error.WriteLine ("ERROR: {0} failed: {1}", callerName, errors);
+ if (errors != null)
throw new MonoBtlsException ("{0} failed: {1}.", callerName, errors);
- } else {
- Console.Error.WriteLine ("ERROR: {0} failed.", callerName);
+ else
throw new MonoBtlsException ("{0} failed.", callerName);
- }
}
MonoBtlsSslError GetError (int ret_code)
{
CheckThrow ();
+ bio.CheckLastError ();
+
var error = mono_btls_ssl_get_error (
Handle.DangerousGetHandle (), ret_code);
return (MonoBtlsSslError)error;
var ret = mono_btls_ssl_read (
Handle.DangerousGetHandle (), data, dataSize);
- if (ret >= 0) {
+ if (ret > 0) {
dataSize = ret;
return MonoBtlsSslError.None;
}
- var error = mono_btls_ssl_get_error (
- Handle.DangerousGetHandle (), ret);
+ var error = GetError (ret);
+ if (ret == 0 && error == MonoBtlsSslError.Syscall) {
+ // End-of-stream
+ dataSize = 0;
+ return MonoBtlsSslError.None;
+ }
+
dataSize = 0;
- return (MonoBtlsSslError)error;
+ return error;
}
public MonoBtlsSslError Write (IntPtr data, ref int dataSize)
return Marshal.PtrToStringAnsi (namePtr);
}
+ public void Shutdown ()
+ {
+ CheckThrow ();
+ var ret = mono_btls_ssl_shutdown (Handle.DangerousGetHandle ());
+ if (ret < 0)
+ throw ThrowError ();
+ }
+
+ public void SetQuietShutdown ()
+ {
+ CheckThrow ();
+ mono_btls_ssl_set_quiet_shutdown (Handle.DangerousGetHandle (), 1);
+ }
+
protected override void Close ()
{
- mono_btls_ssl_close (Handle.DangerousGetHandle ());
+ if (!Handle.IsInvalid)
+ mono_btls_ssl_close (Handle.DangerousGetHandle ());
}
}
}
}
protected override MNS.MobileTlsContext CreateContext (
- MNS.MobileAuthenticatedStream parent, bool serverMode, string targetHost,
- SslProtocols enabledProtocols, X509Certificate serverCertificate,
- X509CertificateCollection clientCertificates, bool askForClientCert)
+ bool serverMode, string targetHost, SslProtocols enabledProtocols,
+ X509Certificate serverCertificate, X509CertificateCollection clientCertificates,
+ bool askForClientCert)
{
return new MonoBtlsContext (
- parent, serverMode, targetHost,
+ this, serverMode, targetHost,
enabledProtocols, serverCertificate,
clientCertificates, askForClientCert);
}
using System.IO;
using System.Net;
using System.Net.Security;
+using System.Security.Authentication;
using SD = System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
+using System.Runtime.ExceptionServices;
namespace Mono.Net.Security
{
- delegate AsyncOperationStatus AsyncOperation (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status);
-
class BufferOffsetSize
{
public byte[] Buffer;
public BufferOffsetSize (byte[] buffer, int offset, int size)
{
+ if (buffer == null)
+ throw new ArgumentNullException (nameof (buffer));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException (nameof (offset));
+ if (size < 0 || offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException (nameof (size));
+
Buffer = buffer;
Offset = offset;
Size = size;
public readonly int InitialSize;
public BufferOffsetSize2 (int size)
- : base (new byte [size], 0, 0)
+ : base (new byte[size], 0, 0)
{
InitialSize = size;
}
{
Offset = Size = 0;
TotalBytes = 0;
- Buffer = new byte [InitialSize];
+ Buffer = new byte[InitialSize];
Complete = false;
}
int missing = size - Remaining;
if (Offset == 0 && Size == 0) {
- Buffer = new byte [size];
+ Buffer = new byte[size];
return;
}
- var buffer = new byte [Buffer.Length + missing];
+ var buffer = new byte[Buffer.Length + missing];
Buffer.CopyTo (buffer, 0);
Buffer = buffer;
}
}
}
- enum AsyncOperationStatus {
- NotStarted,
+ enum AsyncOperationStatus
+ {
Initialize,
Continue,
- Running,
- Complete,
- WantRead,
- WantWrite,
ReadDone,
- FinishWrite
+ Complete
}
- class AsyncProtocolRequest
+ class AsyncProtocolResult
{
- public readonly MobileAuthenticatedStream Parent;
- public readonly BufferOffsetSize UserBuffer;
+ public int UserResult {
+ get;
+ }
+ public ExceptionDispatchInfo Error {
+ get;
+ }
- int RequestedSize;
- public int CurrentSize;
- public int UserResult;
+ public AsyncProtocolResult (int result)
+ {
+ UserResult = result;
+ }
- AsyncOperation Operation;
- int Status;
+ public AsyncProtocolResult (ExceptionDispatchInfo error)
+ {
+ Error = error;
+ }
+ }
- public readonly int ID = ++next_id;
- static int next_id;
+ abstract class AsyncProtocolRequest
+ {
+ public MobileAuthenticatedStream Parent {
+ get;
+ }
- public readonly LazyAsyncResult UserAsyncResult;
+ public bool RunSynchronously {
+ get;
+ }
- public AsyncProtocolRequest (MobileAuthenticatedStream parent, LazyAsyncResult lazyResult, BufferOffsetSize userBuffer = null)
- {
- Parent = parent;
- UserAsyncResult = lazyResult;
- UserBuffer = userBuffer;
+ public int ID => ++next_id;
+
+ public string Name => GetType ().Name;
+
+ public int UserResult {
+ get;
+ protected set;
}
- public bool CompleteWithError (Exception ex)
+ int Started;
+ int RequestedSize;
+ int WriteRequested;
+ readonly object locker = new object ();
+
+ static int next_id;
+
+ public AsyncProtocolRequest (MobileAuthenticatedStream parent, bool sync)
{
- Status = (int)AsyncOperationStatus.Complete;
- if (UserAsyncResult == null)
- return true;
- if (!UserAsyncResult.InternalPeekCompleted)
- UserAsyncResult.InvokeCallback (ex);
- return false;
+ Parent = parent;
+ RunSynchronously = sync;
}
[SD.Conditional ("MARTIN_DEBUG")]
protected void Debug (string message, params object[] args)
{
- Parent.Debug ("AsyncProtocolRequest({0}:{1}): {2}", Parent.ID, ID, string.Format (message, args));
+ Parent.Debug ("{0}({1}:{2}): {3}", Name, Parent.ID, ID, string.Format (message, args));
}
internal void RequestRead (int size)
{
- var oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.WantRead, (int)AsyncOperationStatus.Running);
- Debug ("RequestRead: {0} {1}", oldStatus, size);
- if (oldStatus == AsyncOperationStatus.Running)
- RequestedSize = size;
- else if (oldStatus == AsyncOperationStatus.WantRead)
+ lock (locker) {
RequestedSize += size;
- else if (oldStatus != AsyncOperationStatus.WantWrite)
- throw new InvalidOperationException ();
+ Debug ("RequestRead: {0}", size);
+ }
}
- internal void ResetRead ()
+ internal void RequestWrite ()
{
- var oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.Complete, (int)AsyncOperationStatus.WantRead);
- Debug ("ResetRead: {0} {1}", oldStatus, Status);
+ WriteRequested = 1;
}
- internal void ResetWrite ()
+ internal async Task<AsyncProtocolResult> StartOperation (CancellationToken cancellationToken)
{
- var oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.Complete, (int)AsyncOperationStatus.WantWrite);
- Debug ("ResetWrite: {0} {1}", oldStatus, Status);
+ Debug ("Start Operation: {0}", this);
+ if (Interlocked.CompareExchange (ref Started, 1, 0) != 0)
+ throw new InvalidOperationException ();
+
+ try {
+ await ProcessOperation (cancellationToken).ConfigureAwait (false);
+ return new AsyncProtocolResult (UserResult);
+ } catch (Exception ex) {
+ var info = Parent.SetException (MobileAuthenticatedStream.GetSSPIException (ex));
+ return new AsyncProtocolResult (info);
+ }
}
- internal void RequestWrite ()
+ async Task ProcessOperation (CancellationToken cancellationToken)
{
- var oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.WantWrite, (int)AsyncOperationStatus.Running);
- Debug ("RequestWrite: {0} {1}", oldStatus, Status);
- if (oldStatus == AsyncOperationStatus.Running)
- return;
- else if (oldStatus != AsyncOperationStatus.WantRead && oldStatus != AsyncOperationStatus.WantWrite)
- throw new InvalidOperationException ();
+ var status = AsyncOperationStatus.Initialize;
+ while (status != AsyncOperationStatus.Complete) {
+ cancellationToken.ThrowIfCancellationRequested ();
+ Debug ("ProcessOperation: {0}", status);
+
+ var ret = await InnerRead (cancellationToken).ConfigureAwait (false);
+ if (ret != null) {
+ if (ret == 0) {
+ // End-of-stream
+ Debug ("END OF STREAM!");
+ status = AsyncOperationStatus.ReadDone;
+ } else if (ret < 0) {
+ // remote prematurely closed connection.
+ throw new IOException ("Remote prematurely closed connection.");
+ }
+ }
+
+ Debug ("ProcessOperation run: {0}", status);
+
+ AsyncOperationStatus newStatus;
+ switch (status) {
+ case AsyncOperationStatus.Initialize:
+ case AsyncOperationStatus.Continue:
+ case AsyncOperationStatus.ReadDone:
+ newStatus = Run (status);
+ break;
+ default:
+ throw new InvalidOperationException ();
+ }
+
+ if (Interlocked.Exchange (ref WriteRequested, 0) != 0) {
+ // Flush the write queue.
+ await Parent.InnerWrite (RunSynchronously, cancellationToken);
+ }
+
+ Debug ("ProcessOperation done: {0} -> {1}", status, newStatus);
+
+ status = newStatus;
+ }
}
- internal void StartOperation (AsyncOperation operation)
+ async Task<int?> InnerRead (CancellationToken cancellationToken)
{
- Debug ("Start Operation: {0} {1}", Status, operation);
- if (Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.Initialize, (int)AsyncOperationStatus.NotStarted) != (int)AsyncOperationStatus.NotStarted)
- throw new InvalidOperationException ();
+ int? totalRead = null;
+ var requestedSize = Interlocked.Exchange (ref RequestedSize, 0);
+ while (requestedSize > 0) {
+ Debug ("ProcessOperation - read inner: {0}", requestedSize);
- Operation = operation;
+ var ret = await Parent.InnerRead (RunSynchronously, requestedSize, cancellationToken).ConfigureAwait (false);
+ Debug ("ProcessOperation - read inner done: {0} - {1}", requestedSize, ret);
- if (UserAsyncResult == null) {
- StartOperation ();
- return;
+ if (ret <= 0)
+ return ret;
+ if (ret > requestedSize)
+ throw new InvalidOperationException ();
+
+ totalRead += ret;
+ requestedSize -= ret;
+ var newRequestedSize = Interlocked.Exchange (ref RequestedSize, 0);
+ requestedSize += newRequestedSize;
}
- ThreadPool.QueueUserWorkItem (_ => StartOperation ());
+ return totalRead;
}
- void StartOperation ()
+ /*
+ * This will operate on the internal buffers and never block.
+ */
+ protected abstract AsyncOperationStatus Run (AsyncOperationStatus status);
+
+ public override string ToString ()
{
- try {
- ProcessOperation ();
- if (UserAsyncResult != null && !UserAsyncResult.InternalPeekCompleted)
- UserAsyncResult.InvokeCallback (UserResult);
- } catch (Exception ex) {
- if (UserAsyncResult == null)
- throw;
- if (!UserAsyncResult.InternalPeekCompleted)
- UserAsyncResult.InvokeCallback (ex);
- }
+ return string.Format ("[{0}]", Name);
}
+ }
- void ProcessOperation ()
+ class AsyncHandshakeRequest : AsyncProtocolRequest
+ {
+ public AsyncHandshakeRequest (MobileAuthenticatedStream parent, bool sync)
+ : base (parent, sync)
{
- AsyncOperationStatus status;
- do {
- status = (AsyncOperationStatus)Interlocked.Exchange (ref Status, (int)AsyncOperationStatus.Running);
+ }
- Debug ("ProcessOperation: {0}", status);
+ protected override AsyncOperationStatus Run (AsyncOperationStatus status)
+ {
+ return Parent.ProcessHandshake (status);
+ }
+ }
- status = ProcessOperation (status);
+ abstract class AsyncReadOrWriteRequest : AsyncProtocolRequest
+ {
+ protected BufferOffsetSize UserBuffer {
+ get;
+ }
- Debug ("ProcessOperation done: {0}", status);
+ protected int CurrentSize {
+ get; set;
+ }
- AsyncOperationStatus oldStatus;
- if (status == AsyncOperationStatus.Complete) {
- oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)AsyncOperationStatus.FinishWrite, (int)AsyncOperationStatus.WantWrite);
- if (oldStatus == AsyncOperationStatus.WantWrite) {
- // We are done, but still need to flush the write queue.
- status = AsyncOperationStatus.FinishWrite;
- continue;
- }
- }
+ public AsyncReadOrWriteRequest (MobileAuthenticatedStream parent, bool sync, byte[] buffer, int offset, int size)
+ : base (parent, sync)
+ {
+ UserBuffer = new BufferOffsetSize (buffer, offset, size);
+ }
- oldStatus = (AsyncOperationStatus)Interlocked.CompareExchange (ref Status, (int)status, (int)AsyncOperationStatus.Running);
- Debug ("ProcessOperation done: {0} -> {1}", oldStatus, status);
+ public override string ToString ()
+ {
+ return string.Format ("[{0}: {1}]", Name, UserBuffer);
+ }
+ }
- if (oldStatus != AsyncOperationStatus.Running) {
- if (status == oldStatus || status == AsyncOperationStatus.Continue || status == AsyncOperationStatus.Complete)
- status = oldStatus;
- else
- throw new InvalidOperationException ();
- }
- } while (status != AsyncOperationStatus.Complete);
+ class AsyncReadRequest : AsyncReadOrWriteRequest
+ {
+ public AsyncReadRequest (MobileAuthenticatedStream parent, bool sync, byte[] buffer, int offset, int size)
+ : base (parent, sync, buffer, offset, size)
+ {
}
- AsyncOperationStatus ProcessOperation (AsyncOperationStatus status)
+ protected override AsyncOperationStatus Run (AsyncOperationStatus status)
{
- if (status == AsyncOperationStatus.WantRead) {
- if (RequestedSize < 0)
- throw new InvalidOperationException ();
- else if (RequestedSize == 0)
- return AsyncOperationStatus.Continue;
-
- Debug ("ProcessOperation - read inner: {0}", RequestedSize);
- var ret = Parent.InnerRead (RequestedSize);
- Debug ("ProcessOperation - read inner done: {0} - {1}", RequestedSize, ret);
-
- if (ret < 0)
- return AsyncOperationStatus.ReadDone;
-
- RequestedSize -= ret;
-
- if (ret == 0 || RequestedSize == 0)
- return AsyncOperationStatus.Continue;
- else
- return AsyncOperationStatus.WantRead;
- } else if (status == AsyncOperationStatus.WantWrite) {
- Debug ("ProcessOperation - want write");
- Parent.InnerWrite ();
- Debug ("ProcessOperation - want write done");
+ Debug ("ProcessRead - read user: {0} {1}", this, status);
+
+ var (ret, wantMore) = Parent.ProcessRead (UserBuffer);
+
+ Debug ("ProcessRead - read user done: {0} - {1} {2}", this, ret, wantMore);
+
+ if (ret < 0) {
+ UserResult = -1;
+ return AsyncOperationStatus.Complete;
+ }
+
+ CurrentSize += ret;
+ UserBuffer.Offset += ret;
+ UserBuffer.Size -= ret;
+
+ Debug ("Process Read - read user done #1: {0} - {1} {2}", this, CurrentSize, wantMore);
+
+ if (wantMore && CurrentSize == 0)
return AsyncOperationStatus.Continue;
- } else if (status == AsyncOperationStatus.Initialize || status == AsyncOperationStatus.Continue) {
- Debug ("ProcessOperation - continue");
- status = Operation (this, status);
- Debug ("ProcessOperation - continue done: {0}", status);
- return status;
- } else if (status == AsyncOperationStatus.ReadDone) {
- Debug ("ProcessOperation - read done");
- status = Operation (this, status);
- Debug ("ProcessOperation - read done: {0}", status);
- return status;
- } else if (status == AsyncOperationStatus.FinishWrite) {
- Debug ("ProcessOperation - finish write");
- Parent.InnerWrite ();
- Debug ("ProcessOperation - finish write done");
+
+ UserResult = CurrentSize;
+ return AsyncOperationStatus.Complete;
+ }
+ }
+
+ class AsyncWriteRequest : AsyncReadOrWriteRequest
+ {
+ public AsyncWriteRequest (MobileAuthenticatedStream parent, bool sync, byte[] buffer, int offset, int size)
+ : base (parent, sync, buffer, offset, size)
+ {
+ }
+
+ protected override AsyncOperationStatus Run (AsyncOperationStatus status)
+ {
+ Debug ("ProcessWrite - write user: {0} {1}", this, status);
+
+ if (UserBuffer.Size == 0) {
+ UserResult = CurrentSize;
+ return AsyncOperationStatus.Complete;
+ }
+
+ var (ret, wantMore) = Parent.ProcessWrite (UserBuffer);
+
+ Debug ("ProcessWrite - write user done: {0} - {1} {2}", this, ret, wantMore);
+
+ if (ret < 0) {
+ UserResult = -1;
return AsyncOperationStatus.Complete;
}
- throw new InvalidOperationException ();
+ CurrentSize += ret;
+ UserBuffer.Offset += ret;
+ UserBuffer.Size -= ret;
+
+ if (wantMore)
+ return AsyncOperationStatus.Continue;
+
+ UserResult = CurrentSize;
+ return AsyncOperationStatus.Complete;
+ }
+ }
+
+ class AsyncShutdownRequest : AsyncProtocolRequest
+ {
+ public AsyncShutdownRequest (MobileAuthenticatedStream parent)
+ : base (parent, false)
+ {
+ }
+
+ protected override AsyncOperationStatus Run (AsyncOperationStatus status)
+ {
+ return Parent.ProcessShutdown (status);
}
}
+
}
#endif
#region IMonoSslStream
+ Task IMonoSslStream.ShutdownAsync ()
+ {
+ return Task.CompletedTask;
+ }
+
AuthenticatedStream IMonoSslStream.AuthenticatedStream {
get { return this; }
}
using System.Net;
using System.Net.Security;
using System.Globalization;
+using System.Security.Authentication;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
{
abstract class MobileAuthenticatedStream : AuthenticatedStream, MSI.IMonoSslStream
{
+ /*
+ * This is intentionally called `xobileTlsContext'. It is a "dangerous" object
+ * that must not be touched outside the `ioLock' and we need to be very careful
+ * where we access it.
+ */
MobileTlsContext xobileTlsContext;
- Exception lastException;
+ ExceptionDispatchInfo lastException;
AsyncProtocolRequest asyncHandshakeRequest;
AsyncProtocolRequest asyncReadRequest;
object ioLock = new object ();
int closeRequested;
+ bool shutdown;
static int uniqueNameInteger = 123;
public MobileAuthenticatedStream (Stream innerStream, bool leaveInnerStreamOpen, SslStream owner,
- MSI.MonoTlsSettings settings, MSI.MonoTlsProvider provider)
+ MSI.MonoTlsSettings settings, MSI.MonoTlsProvider provider)
: base (innerStream, leaveInnerStreamOpen)
{
SslStream = owner;
get { return xobileTlsContext != null; }
}
- internal MobileTlsContext Context {
- get {
- CheckThrow (true);
- return xobileTlsContext;
- }
- }
-
- internal void CheckThrow (bool authSuccessCheck)
+ internal void CheckThrow (bool authSuccessCheck, bool shutdownCheck = false)
{
- if (closeRequested != 0)
- throw new InvalidOperationException ("Stream is closed.");
if (lastException != null)
- throw lastException;
+ lastException.Throw ();
if (authSuccessCheck && !IsAuthenticated)
- throw new InvalidOperationException ("Must be authenticated.");
+ throw new InvalidOperationException (SR.net_auth_noauth);
+ if (shutdownCheck && shutdown)
+ throw new InvalidOperationException (SR.net_ssl_io_already_shutdown);
}
- Exception SetException (Exception e)
+ internal static Exception GetSSPIException (Exception e)
{
- e = SetException_internal (e);
- if (e != null && xobileTlsContext != null)
- xobileTlsContext.Dispose ();
- return e;
+ if (e is OperationCanceledException || e is IOException || e is ObjectDisposedException || e is AuthenticationException)
+ return e;
+ return new AuthenticationException (SR.net_auth_SSPI, e);
}
- Exception SetException_internal (Exception e)
+ internal static Exception GetIOException (Exception e, string message)
{
- if (lastException == null)
- lastException = e;
- return lastException;
+ if (e is OperationCanceledException || e is IOException || e is ObjectDisposedException || e is AuthenticationException)
+ return e;
+ return new IOException (message, e);
+ }
+
+ internal ExceptionDispatchInfo SetException (Exception e)
+ {
+ var info = ExceptionDispatchInfo.Capture (e);
+ var old = Interlocked.CompareExchange (ref lastException, info, null);
+ return old ?? info;
}
SslProtocols DefaultProtocols {
get { return SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; }
}
+ enum OperationType {
+ Read,
+ Write,
+ Shutdown
+ }
+
public void AuthenticateAsClient (string targetHost)
{
AuthenticateAsClient (targetHost, new X509CertificateCollection (), DefaultProtocols, false);
public void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
- ValidateCreateContext (false, targetHost, enabledSslProtocols, null, clientCertificates, false);
- ProcessAuthentication (null);
+ var task = ProcessAuthentication (true, false, targetHost, enabledSslProtocols, null, clientCertificates, false);
+ task.Wait ();
}
public IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
public IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
{
- ValidateCreateContext (false, targetHost, enabledSslProtocols, null, clientCertificates, false);
- var result = new LazyAsyncResult (this, asyncState, asyncCallback);
- ProcessAuthentication (result);
- return result;
+ var task = ProcessAuthentication (false, false, targetHost, enabledSslProtocols, null, clientCertificates, false);
+ return TaskToApm.Begin (task, asyncCallback, asyncState);
}
public void EndAuthenticateAsClient (IAsyncResult asyncResult)
{
- EndProcessAuthentication (asyncResult);
+ TaskToApm.End (asyncResult);
}
public void AuthenticateAsServer (X509Certificate serverCertificate)
public void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
- ValidateCreateContext (true, string.Empty, enabledSslProtocols, serverCertificate, null, clientCertificateRequired);
- ProcessAuthentication (null);
+ var task = ProcessAuthentication (true, true, string.Empty, enabledSslProtocols, serverCertificate, null, clientCertificateRequired);
+ task.Wait ();
}
public IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState)
public IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
{
- ValidateCreateContext (true, string.Empty, enabledSslProtocols, serverCertificate, null, clientCertificateRequired);
- var result = new LazyAsyncResult (this, asyncState, asyncCallback);
- ProcessAuthentication (result);
- return result;
+ var task = ProcessAuthentication (false, true, string.Empty, enabledSslProtocols, serverCertificate, null, clientCertificateRequired);
+ return TaskToApm.Begin (task, asyncCallback, asyncState);
}
public void EndAuthenticateAsServer (IAsyncResult asyncResult)
{
- EndProcessAuthentication (asyncResult);
+ TaskToApm.End (asyncResult);
}
public Task AuthenticateAsClientAsync (string targetHost)
{
- return Task.Factory.FromAsync (BeginAuthenticateAsClient, EndAuthenticateAsClient, targetHost, null);
+ return ProcessAuthentication (false, false, targetHost, DefaultProtocols, null, null, false);
}
public Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
- return Task.Factory.FromAsync ((callback, state) => BeginAuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, callback, state), EndAuthenticateAsClient, null);
+ return ProcessAuthentication (false, false, targetHost, enabledSslProtocols, null, clientCertificates, false);
}
public Task AuthenticateAsServerAsync (X509Certificate serverCertificate)
{
- return Task.Factory.FromAsync (BeginAuthenticateAsServer, EndAuthenticateAsServer, serverCertificate, null);
+ return AuthenticateAsServerAsync (serverCertificate, false, DefaultProtocols, false);
}
public Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
- return Task.Factory.FromAsync ((callback, state) => BeginAuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, callback, state), EndAuthenticateAsServer, null);
+ return ProcessAuthentication (false, true, string.Empty, enabledSslProtocols, serverCertificate, null, clientCertificateRequired);
+ }
+
+ public Task ShutdownAsync ()
+ {
+ Debug ("ShutdownAsync");
+
+ /*
+ * SSLClose() is a little bit tricky as it might attempt to send a close_notify alert
+ * and thus call our write callback.
+ *
+ * It is also not thread-safe with SSLRead() or SSLWrite(), so we need to take the I/O lock here.
+ */
+ var asyncRequest = new AsyncShutdownRequest (this);
+ var task = StartOperation (OperationType.Shutdown, asyncRequest, CancellationToken.None);
+ return task;
}
public AuthenticatedStream AuthenticatedStream {
get { return this; }
}
- internal void ProcessAuthentication (LazyAsyncResult lazyResult)
+ async Task ProcessAuthentication (
+ bool runSynchronously, bool serverMode, string targetHost, SslProtocols enabledProtocols,
+ X509Certificate serverCertificate, X509CertificateCollection clientCertificates, bool clientCertRequired)
{
- var asyncRequest = new AsyncProtocolRequest (this, lazyResult);
+ if (serverMode) {
+ if (serverCertificate == null)
+ throw new ArgumentException (nameof (serverCertificate));
+ } else {
+ if (targetHost == null)
+ throw new ArgumentException (nameof (targetHost));
+ if (targetHost.Length == 0)
+ targetHost = "?" + Interlocked.Increment (ref uniqueNameInteger).ToString (NumberFormatInfo.InvariantInfo);
+ }
+
+ if (lastException != null)
+ lastException.Throw ();
+
+ var asyncRequest = new AsyncHandshakeRequest (this, runSynchronously);
if (Interlocked.CompareExchange (ref asyncHandshakeRequest, asyncRequest, null) != null)
throw new InvalidOperationException ("Invalid nested call.");
+ // Make sure no other async requests can be started during the handshake.
+ if (Interlocked.CompareExchange (ref asyncReadRequest, asyncRequest, null) != null)
+ throw new InvalidOperationException ("Invalid nested call.");
+ if (Interlocked.CompareExchange (ref asyncWriteRequest, asyncRequest, null) != null)
+ throw new InvalidOperationException ("Invalid nested call.");
+
+ AsyncProtocolResult result;
try {
- if (lastException != null)
- throw lastException;
- if (xobileTlsContext == null)
- throw new InvalidOperationException ();
+ lock (ioLock) {
+ if (xobileTlsContext != null)
+ throw new InvalidOperationException ();
+ readBuffer.Reset ();
+ writeBuffer.Reset ();
- readBuffer.Reset ();
- writeBuffer.Reset ();
+ xobileTlsContext = CreateContext (
+ serverMode, targetHost, enabledProtocols, serverCertificate,
+ clientCertificates, clientCertRequired);
+ }
try {
- asyncRequest.StartOperation (ProcessHandshake);
+ result = await asyncRequest.StartOperation (CancellationToken.None).ConfigureAwait (false);
} catch (Exception ex) {
- ExceptionDispatchInfo.Capture (SetException (ex)).Throw ();
+ result = new AsyncProtocolResult (SetException (GetSSPIException (ex)));
}
} finally {
- if (lazyResult == null || lastException != null) {
+ lock (ioLock) {
readBuffer.Reset ();
writeBuffer.Reset ();
+ asyncWriteRequest = null;
+ asyncReadRequest = null;
asyncHandshakeRequest = null;
}
}
- }
-
- internal void EndProcessAuthentication (IAsyncResult result)
- {
- if (result == null)
- throw new ArgumentNullException ("asyncResult");
-
- var lazyResult = (LazyAsyncResult)result;
- if (Interlocked.Exchange (ref asyncHandshakeRequest, null) == null)
- throw new InvalidOperationException ("Invalid end call.");
-
- lazyResult.InternalWaitForCompletion ();
-
- readBuffer.Reset ();
- writeBuffer.Reset ();
-
- var e = lazyResult.Result as Exception;
- if (e != null)
- ExceptionDispatchInfo.Capture (SetException (e)).Throw ();
- }
-
- internal void ValidateCreateContext (bool serverMode, string targetHost, SslProtocols enabledProtocols, X509Certificate serverCertificate, X509CertificateCollection clientCertificates, bool clientCertRequired)
- {
- if (xobileTlsContext != null)
- throw new InvalidOperationException ();
-
- if (serverMode) {
- if (serverCertificate == null)
- throw new ArgumentException ("serverCertificate");
- } else {
- if (targetHost == null)
- throw new ArgumentException ("targetHost");
- if (targetHost.Length == 0)
- targetHost = "?" + Interlocked.Increment (ref uniqueNameInteger).ToString (NumberFormatInfo.InvariantInfo);
- }
- xobileTlsContext = CreateContext (this, serverMode, targetHost, enabledProtocols, serverCertificate, clientCertificates, clientCertRequired);
+ if (result.Error != null)
+ result.Error.Throw ();
}
protected abstract MobileTlsContext CreateContext (
- MobileAuthenticatedStream parent, bool serverMode, string targetHost,
- SSA.SslProtocols enabledProtocols, X509Certificate serverCertificate,
- X509CertificateCollection clientCertificates, bool askForClientCert);
+ bool serverMode, string targetHost, SSA.SslProtocols enabledProtocols,
+ X509Certificate serverCertificate, X509CertificateCollection clientCertificates,
+ bool askForClientCert);
public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
- return BeginReadOrWrite (ref asyncReadRequest, ref readBuffer, ProcessRead, new BufferOffsetSize (buffer, offset, count), asyncCallback, asyncState);
+ var asyncRequest = new AsyncReadRequest (this, false, buffer, offset, count);
+ var task = StartOperation (OperationType.Read, asyncRequest, CancellationToken.None);
+ return TaskToApm.Begin (task, asyncCallback, asyncState);
}
public override int EndRead (IAsyncResult asyncResult)
{
- return (int)EndReadOrWrite (asyncResult, ref asyncReadRequest);
+ return TaskToApm.End<int> (asyncResult);
}
public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
- return BeginReadOrWrite (ref asyncWriteRequest, ref writeBuffer, ProcessWrite, new BufferOffsetSize (buffer, offset, count), asyncCallback, asyncState);
+ var asyncRequest = new AsyncWriteRequest (this, false, buffer, offset, count);
+ var task = StartOperation (OperationType.Write, asyncRequest, CancellationToken.None);
+ return TaskToApm.Begin (task, asyncCallback, asyncState);
}
public override void EndWrite (IAsyncResult asyncResult)
{
- EndReadOrWrite (asyncResult, ref asyncWriteRequest);
+ TaskToApm.End (asyncResult);
}
public override int Read (byte[] buffer, int offset, int count)
{
- return ProcessReadOrWrite (ref asyncReadRequest, ref readBuffer, ProcessRead, new BufferOffsetSize (buffer, offset, count), null);
+ var asyncRequest = new AsyncReadRequest (this, true, buffer, offset, count);
+ var task = StartOperation (OperationType.Read, asyncRequest, CancellationToken.None);
+ return task.Result;
}
public void Write (byte[] buffer)
{
Write (buffer, 0, buffer.Length);
}
+
public override void Write (byte[] buffer, int offset, int count)
{
- ProcessReadOrWrite (ref asyncWriteRequest, ref writeBuffer, ProcessWrite, new BufferOffsetSize (buffer, offset, count), null);
+ var asyncRequest = new AsyncWriteRequest (this, true, buffer, offset, count);
+ var task = StartOperation (OperationType.Write, asyncRequest, CancellationToken.None);
+ task.Wait ();
}
- IAsyncResult BeginReadOrWrite (ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, AsyncCallback asyncCallback, object asyncState)
+ public override Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
- LazyAsyncResult lazyResult = new LazyAsyncResult (this, asyncState, asyncCallback);
- ProcessReadOrWrite (ref nestedRequest, ref internalBuffer, operation, userBuffer, lazyResult);
- return lazyResult;
+ var asyncRequest = new AsyncReadRequest (this, false, buffer, offset, count);
+ return StartOperation (OperationType.Read, asyncRequest, cancellationToken);
}
- object EndReadOrWrite (IAsyncResult asyncResult, ref AsyncProtocolRequest nestedRequest)
+ public override Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
- if (asyncResult == null)
- throw new ArgumentNullException("asyncResult");
-
- var lazyResult = (LazyAsyncResult)asyncResult;
-
- if (Interlocked.Exchange (ref nestedRequest, null) == null)
- throw new InvalidOperationException ("Invalid end call.");
-
- // No "artificial" timeouts implemented so far, InnerStream controls timeout.
- lazyResult.InternalWaitForCompletion ();
-
- Debug ("EndReadOrWrite");
-
- var e = lazyResult.Result as Exception;
- if (e != null) {
- var ioEx = e as IOException;
- if (ioEx != null)
- throw ioEx;
- throw new IOException ("read failed", e);
- }
-
- return lazyResult.Result;
+ var asyncRequest = new AsyncWriteRequest (this, false, buffer, offset, count);
+ return StartOperation (OperationType.Write, asyncRequest, cancellationToken);
}
- int ProcessReadOrWrite (ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, LazyAsyncResult lazyResult)
+ async Task<int> StartOperation (OperationType type, AsyncProtocolRequest asyncRequest, CancellationToken cancellationToken)
{
- if (userBuffer == null || userBuffer.Buffer == null)
- throw new ArgumentNullException ("buffer");
- if (userBuffer.Offset < 0)
- throw new ArgumentOutOfRangeException ("offset");
- if (userBuffer.Size < 0 || userBuffer.Offset + userBuffer.Size > userBuffer.Buffer.Length)
- throw new ArgumentOutOfRangeException ("count");
-
- CheckThrow (true);
+ CheckThrow (true, type != OperationType.Read);
+ Debug ("StartOperationAsync: {0} {1}", asyncRequest, type);
- var name = internalBuffer == readBuffer ? "read" : "write";
- Debug ("ProcessReadOrWrite: {0} {1}", name, userBuffer);
+ if (type == OperationType.Read) {
+ if (Interlocked.CompareExchange (ref asyncReadRequest, asyncRequest, null) != null)
+ throw new InvalidOperationException ("Invalid nested call.");
+ } else {
+ if (Interlocked.CompareExchange (ref asyncWriteRequest, asyncRequest, null) != null)
+ throw new InvalidOperationException ("Invalid nested call.");
+ }
- var asyncRequest = new AsyncProtocolRequest (this, lazyResult, userBuffer);
- return StartOperation (ref nestedRequest, ref internalBuffer, operation, asyncRequest, name);
- }
+ AsyncProtocolResult result;
- int StartOperation (ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, AsyncProtocolRequest asyncRequest, string name)
- {
- if (Interlocked.CompareExchange (ref nestedRequest, asyncRequest, null) != null)
- throw new InvalidOperationException ("Invalid nested call.");
-
- bool failed = false;
try {
- internalBuffer.Reset ();
- asyncRequest.StartOperation (operation);
- return asyncRequest.UserResult;
+ lock (ioLock) {
+ if (type == OperationType.Read)
+ readBuffer.Reset ();
+ else
+ writeBuffer.Reset ();
+ }
+ result = await asyncRequest.StartOperation (cancellationToken).ConfigureAwait (false);
} catch (Exception e) {
- failed = true;
- if (e is IOException)
- throw;
- throw new IOException (name + " failed", e);
+ var info = SetException (GetIOException (e, asyncRequest.Name + " failed"));
+ result = new AsyncProtocolResult (info);
} finally {
- if (asyncRequest.UserAsyncResult == null || failed) {
- internalBuffer.Reset ();
- nestedRequest = null;
+ lock (ioLock) {
+ if (type == OperationType.Read) {
+ readBuffer.Reset ();
+ asyncReadRequest = null;
+ } else {
+ writeBuffer.Reset ();
+ asyncWriteRequest = null;
+ }
}
}
+
+ if (result.Error != null)
+ result.Error.Throw ();
+ return result.UserResult;
}
static int nextId;
Console.Error.WriteLine ("MobileAuthenticatedStream({0}): {1}", ID, string.Format (message, args));
}
- #region Called back from native code via SslConnection
+#region Called back from native code via SslConnection
/*
* Called from within SSLRead() and SSLHandshake(). We only access tha managed byte[] here.
*/
- internal int InternalRead (byte[] buffer, int offset, int size, out bool wantMore)
+ internal int InternalRead (byte[] buffer, int offset, int size, out bool outWantMore)
{
try {
- Debug ("InternalRead: {0} {1} {2} {3}", offset, size, asyncReadRequest != null, readBuffer != null);
+ Debug ("InternalRead: {0} {1} {2} {3} {4}", offset, size,
+ asyncHandshakeRequest != null ? "handshake" : "",
+ asyncReadRequest != null ? "async" : "",
+ readBuffer != null ? readBuffer.ToString () : "");
var asyncRequest = asyncHandshakeRequest ?? asyncReadRequest;
- return InternalRead (asyncRequest, readBuffer, buffer, offset, size, out wantMore);
+ var (ret, wantMore) = InternalRead (asyncRequest, readBuffer, buffer, offset, size);
+ outWantMore = wantMore;
+ return ret;
} catch (Exception ex) {
Debug ("InternalRead failed: {0}", ex);
- SetException_internal (ex);
- wantMore = false;
+ SetException (GetIOException (ex, "InternalRead() failed"));
+ outWantMore = false;
return -1;
}
}
- int InternalRead (AsyncProtocolRequest asyncRequest, BufferOffsetSize internalBuffer, byte[] buffer, int offset, int size, out bool wantMore)
+ (int, bool) InternalRead (AsyncProtocolRequest asyncRequest, BufferOffsetSize internalBuffer, byte[] buffer, int offset, int size)
{
if (asyncRequest == null)
throw new InvalidOperationException ();
* native function again.
*/
if (internalBuffer.Size == 0 && !internalBuffer.Complete) {
- Debug ("InternalRead #1: {0} {1}", internalBuffer.Offset, internalBuffer.TotalBytes);
+ Debug ("InternalRead #1: {0} {1} {2}", internalBuffer.Offset, internalBuffer.TotalBytes, size);
internalBuffer.Offset = internalBuffer.Size = 0;
asyncRequest.RequestRead (size);
- wantMore = true;
- return 0;
+ return (0, true);
}
/*
Buffer.BlockCopy (internalBuffer.Buffer, internalBuffer.Offset, buffer, offset, len);
internalBuffer.Offset += len;
internalBuffer.Size -= len;
- wantMore = !internalBuffer.Complete && len < size;
- return len;
+ return (len, !internalBuffer.Complete && len < size);
}
/*
return InternalWrite (asyncRequest, writeBuffer, buffer, offset, size);
} catch (Exception ex) {
Debug ("InternalWrite failed: {0}", ex);
- SetException_internal (ex);
+ SetException (GetIOException (ex, "InternalWrite() failed"));
return false;
}
}
return true;
}
- #endregion
+#endregion
- #region Inner Stream
+#region Inner Stream
/*
* Read / write data from the inner stream; we're only called from managed code and only manipulate
* the internal buffers.
*/
- internal int InnerRead (int requestedSize)
+ internal async Task<int> InnerRead (bool sync, int requestedSize, CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested ();
Debug ("InnerRead: {0} {1} {2} {3}", readBuffer.Offset, readBuffer.Size, readBuffer.Remaining, requestedSize);
var len = System.Math.Min (readBuffer.Remaining, requestedSize);
if (len == 0)
throw new InvalidOperationException ();
- var ret = InnerStream.Read (readBuffer.Buffer, readBuffer.EndOffset, len);
+
+ Task<int> task;
+ if (sync)
+ task = Task.Run (() => InnerStream.Read (readBuffer.Buffer, readBuffer.EndOffset, len));
+ else
+ task = InnerStream.ReadAsync (readBuffer.Buffer, readBuffer.EndOffset, len, cancellationToken);
+
+ var ret = await task.ConfigureAwait (false);
Debug ("InnerRead done: {0} {1} - {2}", readBuffer.Remaining, len, ret);
if (ret >= 0) {
return ret;
}
- internal void InnerWrite ()
+ internal async Task InnerWrite (bool sync, CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested ();
Debug ("InnerWrite: {0} {1}", writeBuffer.Offset, writeBuffer.Size);
- InnerFlush ();
- }
- internal void InnerFlush ()
- {
- if (writeBuffer.Size > 0) {
- InnerStream.Write (writeBuffer.Buffer, writeBuffer.Offset, writeBuffer.Size);
- writeBuffer.TotalBytes += writeBuffer.Size;
- writeBuffer.Offset = writeBuffer.Size = 0;
- }
+ if (writeBuffer.Size == 0)
+ return;
+
+ Task task;
+ if (sync)
+ task = Task.Run (() => InnerStream.Write (writeBuffer.Buffer, writeBuffer.Offset, writeBuffer.Size));
+ else
+ task = InnerStream.WriteAsync (writeBuffer.Buffer, writeBuffer.Offset, writeBuffer.Size);
+
+ await task.ConfigureAwait (false);
+
+ writeBuffer.TotalBytes += writeBuffer.Size;
+ writeBuffer.Offset = writeBuffer.Size = 0;
}
- #endregion
+#endregion
- #region Main async I/O loop
+#region Main async I/O loop
- AsyncOperationStatus ProcessHandshake (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status)
+ internal AsyncOperationStatus ProcessHandshake (AsyncOperationStatus status)
{
Debug ("ProcessHandshake: {0}", status);
- /*
- * The first time we're called (AsyncOperationStatus.Initialize), we need to setup the SslContext and
- * start the handshake.
- */
- if (status == AsyncOperationStatus.Initialize) {
- xobileTlsContext.StartHandshake ();
- return AsyncOperationStatus.Continue;
- } else if (status == AsyncOperationStatus.ReadDone) {
- // remote prematurely closed connection.
- throw new IOException ("Remote prematurely closed connection.");
- } else if (status != AsyncOperationStatus.Continue) {
- throw new InvalidOperationException ();
- }
+ lock (ioLock) {
+ /*
+ * The first time we're called (AsyncOperationStatus.Initialize), we need to setup the SslContext and
+ * start the handshake.
+ */
+ if (status == AsyncOperationStatus.Initialize) {
+ xobileTlsContext.StartHandshake ();
+ return AsyncOperationStatus.Continue;
+ } else if (status == AsyncOperationStatus.ReadDone) {
+ throw new IOException (SR.net_auth_eof);
+ } else if (status != AsyncOperationStatus.Continue) {
+ throw new InvalidOperationException ();
+ }
- /*
- * SSLHandshake() will return repeatedly with 'SslStatus.WouldBlock', we then need
- * to take care of I/O and call it again.
- */
- if (!xobileTlsContext.ProcessHandshake ()) {
/*
- * Flush the internal write buffer.
- */
- InnerFlush ();
+ * SSLHandshake() will return repeatedly with 'SslStatus.WouldBlock', we then need
+ * to take care of I/O and call it again.
+ */
+ if (xobileTlsContext.ProcessHandshake ()) {
+ xobileTlsContext.FinishHandshake ();
+ return AsyncOperationStatus.Complete;
+ }
return AsyncOperationStatus.Continue;
}
-
- xobileTlsContext.FinishHandshake ();
- return AsyncOperationStatus.Complete;
}
- AsyncOperationStatus ProcessRead (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status)
+ internal (int, bool) ProcessRead (BufferOffsetSize userBuffer)
{
- Debug ("ProcessRead - read user: {0} {1}", status, asyncRequest.UserBuffer);
-
- int ret;
- bool wantMore;
lock (ioLock) {
- ret = Context.Read (asyncRequest.UserBuffer.Buffer, asyncRequest.UserBuffer.Offset, asyncRequest.UserBuffer.Size, out wantMore);
+ // This operates on the internal buffer and will never block.
+ var ret = xobileTlsContext.Read (userBuffer.Buffer, userBuffer.Offset, userBuffer.Size, out bool wantMore);
+ return (ret, wantMore);
}
- Debug ("ProcessRead - read user done: {0} - {1} {2}", asyncRequest.UserBuffer, ret, wantMore);
-
- if (ret < 0) {
- asyncRequest.UserResult = -1;
- return AsyncOperationStatus.Complete;
- }
-
- asyncRequest.CurrentSize += ret;
- asyncRequest.UserBuffer.Offset += ret;
- asyncRequest.UserBuffer.Size -= ret;
-
- Debug ("Process Read - read user done #1: {0} - {1} {2}", asyncRequest.UserBuffer, asyncRequest.CurrentSize, wantMore);
-
- if (wantMore && asyncRequest.CurrentSize == 0)
- return AsyncOperationStatus.WantRead;
-
- asyncRequest.ResetRead ();
- asyncRequest.UserResult = asyncRequest.CurrentSize;
- return AsyncOperationStatus.Complete;
}
- AsyncOperationStatus ProcessWrite (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status)
+ internal (int, bool) ProcessWrite (BufferOffsetSize userBuffer)
{
- Debug ("ProcessWrite - write user: {0} {1}", status, asyncRequest.UserBuffer);
-
- if (asyncRequest.UserBuffer.Size == 0) {
- asyncRequest.UserResult = asyncRequest.CurrentSize;
- return AsyncOperationStatus.Complete;
- }
-
- int ret;
- bool wantMore;
lock (ioLock) {
- ret = Context.Write (asyncRequest.UserBuffer.Buffer, asyncRequest.UserBuffer.Offset, asyncRequest.UserBuffer.Size, out wantMore);
- }
- Debug ("ProcessWrite - write user done: {0} - {1} {2}", asyncRequest.UserBuffer, ret, wantMore);
-
- if (ret < 0) {
- asyncRequest.UserResult = -1;
- return AsyncOperationStatus.Complete;
+ // This operates on the internal buffer and will never block.
+ var ret = xobileTlsContext.Write (userBuffer.Buffer, userBuffer.Offset, userBuffer.Size, out bool wantMore);
+ return (ret, wantMore);
}
-
- asyncRequest.CurrentSize += ret;
- asyncRequest.UserBuffer.Offset += ret;
- asyncRequest.UserBuffer.Size -= ret;
-
- if (wantMore || writeBuffer.Size > 0)
- return AsyncOperationStatus.WantWrite;
-
- asyncRequest.ResetWrite ();
- asyncRequest.UserResult = asyncRequest.CurrentSize;
- return AsyncOperationStatus.Complete;
}
- AsyncOperationStatus ProcessClose (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status)
+ internal AsyncOperationStatus ProcessShutdown (AsyncOperationStatus status)
{
- Debug ("ProcessClose: {0}", status);
+ Debug ("ProcessShutdown: {0}", status);
lock (ioLock) {
- if (xobileTlsContext == null)
- return AsyncOperationStatus.Complete;
-
- xobileTlsContext.Close ();
- xobileTlsContext = null;
- return AsyncOperationStatus.Continue;
+ xobileTlsContext.Shutdown ();
+ shutdown = true;
+ return AsyncOperationStatus.Complete;
}
}
- AsyncOperationStatus ProcessFlush (AsyncProtocolRequest asyncRequest, AsyncOperationStatus status)
- {
- Debug ("ProcessFlush: {0}", status);
- return AsyncOperationStatus.Complete;
- }
-
- #endregion
+#endregion
public override bool IsServer {
- get { return xobileTlsContext != null && xobileTlsContext.IsServer; }
+ get {
+ CheckThrow (false);
+ return xobileTlsContext != null && xobileTlsContext.IsServer;
+ }
}
public override bool IsAuthenticated {
- get { return xobileTlsContext != null && lastException == null && xobileTlsContext.IsAuthenticated; }
+ get {
+ lock (ioLock) {
+ // Don't use CheckThrow(), we want to return false if we're not authenticated.
+ return xobileTlsContext != null && lastException == null && xobileTlsContext.IsAuthenticated;
+ }
+ }
}
public override bool IsMutuallyAuthenticated {
get {
- return IsAuthenticated &&
- (Context.IsServer? Context.LocalServerCertificate: Context.LocalClientCertificate) != null &&
- Context.IsRemoteCertificateAvailable;
+ lock (ioLock) {
+ // Don't use CheckThrow() here.
+ if (!IsAuthenticated)
+ return false;
+ if ((xobileTlsContext.IsServer ? xobileTlsContext.LocalServerCertificate : xobileTlsContext.LocalClientCertificate) == null)
+ return false;
+ return xobileTlsContext.IsRemoteCertificateAvailable;
+ }
}
}
protected override void Dispose (bool disposing)
{
try {
- lastException = new ObjectDisposedException ("MobileAuthenticatedStream");
lock (ioLock) {
+ Debug ("Dispose: {0}", xobileTlsContext != null);
+ lastException = ExceptionDispatchInfo.Capture (new ObjectDisposedException ("MobileAuthenticatedStream"));
if (xobileTlsContext != null) {
xobileTlsContext.Dispose ();
xobileTlsContext = null;
public override void Flush ()
{
- CheckThrow (true);
- var asyncRequest = new AsyncProtocolRequest (this, null);
- StartOperation (ref asyncWriteRequest, ref writeBuffer, ProcessFlush, asyncRequest, "flush");
+ // Write() automatically flushes the underlying stream.
}
- public override void Close ()
- {
- /*
- * SSLClose() is a little bit tricky as it might attempt to send a close_notify alert
- * and thus call our write callback.
- *
- * It is also not thread-safe with SSLRead() or SSLWrite(), so we need to take the I/O lock here.
- */
- if (Interlocked.Exchange (ref closeRequested, 1) == 1)
- return;
- if (xobileTlsContext == null)
- return;
+ public SslProtocols SslProtocol {
+ get {
+ lock (ioLock) {
+ CheckThrow (true);
+ return (SslProtocols)xobileTlsContext.NegotiatedProtocol;
+ }
+ }
+ }
+
+ public X509Certificate RemoteCertificate {
+ get {
+ lock (ioLock) {
+ CheckThrow (true);
+ return xobileTlsContext.RemoteCertificate;
+ }
+ }
+ }
+
+ public X509Certificate LocalCertificate {
+ get {
+ lock (ioLock) {
+ CheckThrow (true);
+ return InternalLocalCertificate;
+ }
+ }
+ }
+
+ public X509Certificate InternalLocalCertificate {
+ get {
+ lock (ioLock) {
+ CheckThrow (false);
+ if (xobileTlsContext == null)
+ return null;
+ return xobileTlsContext.IsServer ? xobileTlsContext.LocalServerCertificate : xobileTlsContext.LocalClientCertificate;
+ }
+ }
+ }
- var asyncRequest = new AsyncProtocolRequest (this, null);
- StartOperation (ref asyncWriteRequest, ref writeBuffer, ProcessClose, asyncRequest, "close");
+ public MSI.MonoTlsConnectionInfo GetConnectionInfo ()
+ {
+ lock (ioLock) {
+ CheckThrow (true);
+ return xobileTlsContext.ConnectionInfo;
+ }
}
//
}
public override bool CanWrite {
- get { return IsAuthenticated & InnerStream.CanWrite; }
+ get { return IsAuthenticated & InnerStream.CanWrite && !shutdown; }
}
public override bool CanSeek {
set { InnerStream.WriteTimeout = value; }
}
- public SslProtocols SslProtocol {
- get {
- CheckThrow (true);
- return (SslProtocols)Context.NegotiatedProtocol;
- }
- }
-
- public X509Certificate RemoteCertificate {
- get {
- CheckThrow (true);
- return Context.RemoteCertificate;
- }
- }
-
- public X509Certificate LocalCertificate {
- get {
- CheckThrow (true);
- return InternalLocalCertificate;
- }
- }
-
- public X509Certificate InternalLocalCertificate {
- get {
- CheckThrow (false);
- if (!HasContext)
- return null;
- return Context.IsServer ? Context.LocalServerCertificate : Context.LocalClientCertificate;
- }
- }
-
- public MSI.MonoTlsConnectionInfo GetConnectionInfo ()
- {
- CheckThrow (true);
- return Context.ConnectionInfo;
- }
-
public SSA.CipherAlgorithmType CipherAlgorithm {
get {
CheckThrow (true);
- var info = Context.ConnectionInfo;
+ var info = GetConnectionInfo ();
if (info == null)
return SSA.CipherAlgorithmType.None;
switch (info.CipherAlgorithmType) {
public SSA.HashAlgorithmType HashAlgorithm {
get {
CheckThrow (true);
- var info = Context.ConnectionInfo;
+ var info = GetConnectionInfo ();
if (info == null)
return SSA.HashAlgorithmType.None;
switch (info.HashAlgorithmType) {
public SSA.ExchangeAlgorithmType KeyExchangeAlgorithm {
get {
CheckThrow (true);
- var info = Context.ConnectionInfo;
+ var info = GetConnectionInfo ();
if (info == null)
return SSA.ExchangeAlgorithmType.None;
switch (info.ExchangeAlgorithmType) {
}
}
- #region Need to Implement
+#region Need to Implement
public int CipherStrength {
get {
throw new NotImplementedException ();
}
}
- #endregion
+#endregion
}
}
#endif
public abstract int Write (byte[] buffer, int offset, int count, out bool wantMore);
- public abstract void Close ();
+ public abstract void Shutdown ();
protected bool ValidateCertificate (X509Certificate leaf, X509Chain chain)
{
if (initialized)
return;
+ InitializeProviderRegistration ();
+
MSI.MonoTlsProvider provider;
try {
provider = CreateDefaultProviderImpl ();
{
public const string mono_net_io_shutdown = "mono_net_io_shutdown";
public const string mono_net_io_renegotiate = "mono_net_io_renegotiate";
+
+ public const string net_ssl_io_already_shutdown = "Write operations are not allowed after the channel was shutdown.";
public const string net_log_set_socketoption_reuseport_default_on = "net_log_set_socketoption_reuseport_default_on";
public const string net_log_set_socketoption_reuseport_not_supported = "net_log_set_socketoption_reuseport_not_supported";
properties = new ConfigurationPropertyCollection ();
properties.Add (bypassListProp);
+ properties.Add (enabledProp);
properties.Add (moduleProp);
properties.Add (proxyProp);
+ properties.Add (useDefaultCredentialsProp);
}
public DefaultProxySection ()
properties = new ConfigurationPropertyCollection ();
+ properties.Add (autoDetectProp);
properties.Add (bypassOnLocalProp);
properties.Add (proxyAddressProp);
properties.Add (scriptLocationProp);
return Impl.AuthenticateAsServerAsync (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation);
}
+ public virtual Task ShutdownAsync ()
+ {
+ return Impl.ShutdownAsync ();
+ }
+
public override bool IsAuthenticated {
get { return Impl.IsAuthenticated; }
}
throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
}
+ public virtual Task ShutdownAsync ()
+ {
+ throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
+ }
+
public override bool IsAuthenticated {
get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
}
EndPoint = remoteEP,
};
- // Bug #75154: Connect() should not succeed for .Any addresses.
- if (remoteEP is IPEndPoint) {
- IPEndPoint ep = (IPEndPoint) remoteEP;
- if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
- sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
- return sockares;
- }
-
- sockares.EndPoint = remoteEP = RemapIPEndPoint (ep);
- }
-
- int error = 0;
-
- if (connect_in_progress) {
- // This could happen when multiple IPs are used
- // Calling connect() again will reset the connection attempt and cause
- // an error. Better to just close the socket and move on.
- connect_in_progress = false;
- m_Handle.Dispose ();
- m_Handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
- if (error != 0)
- throw new SocketException (error);
- }
-
- bool blk = is_blocking;
- if (blk)
- Blocking = false;
- Connect_internal (m_Handle, remoteEP.Serialize (), out error, false);
- if (blk)
- Blocking = true;
-
- if (error == 0) {
- // succeeded synch
- is_connected = true;
- is_bound = true;
- sockares.Complete (true);
- return sockares;
- }
-
- if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
- // error synch
- is_connected = false;
- is_bound = false;
- sockares.Complete (new SocketException (error), true);
- return sockares;
- }
-
- // continue asynch
- is_connected = false;
- is_bound = false;
- connect_in_progress = true;
-
- IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
-
+ BeginSConnect (sockares);
return sockares;
}
is_connected = false;
- return BeginMConnect (sockares);
+ BeginMConnect (sockares);
+ return sockares;
}
- internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
+ static void BeginMConnect (SocketAsyncResult sockares)
{
- SocketAsyncResult ares = null;
Exception exc = null;
- AsyncCallback callback;
for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
try {
sockares.CurrentAddress++;
+ sockares.EndPoint = new IPEndPoint (sockares.Addresses [i], sockares.Port);
- ares = (SocketAsyncResult) BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
- if (ares.IsCompleted && ares.CompletedSynchronously) {
- ares.CheckIfThrowDelayedException ();
-
- callback = ares.AsyncCallback;
- if (callback != null)
- ThreadPool.UnsafeQueueUserWorkItem (_ => callback (ares), null);
- }
-
- break;
+ BeginSConnect (sockares);
+ return;
} catch (Exception e) {
exc = e;
- ares = null;
}
}
- if (ares == null)
- throw exc;
+ throw exc;
+ }
- return sockares;
+ static void BeginSConnect (SocketAsyncResult sockares)
+ {
+ EndPoint remoteEP = sockares.EndPoint;
+ // Bug #75154: Connect() should not succeed for .Any addresses.
+ if (remoteEP is IPEndPoint) {
+ IPEndPoint ep = (IPEndPoint) remoteEP;
+ if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
+ sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
+ return;
+ }
+
+ sockares.EndPoint = remoteEP = sockares.socket.RemapIPEndPoint (ep);
+ }
+
+ int error = 0;
+
+ if (sockares.socket.connect_in_progress) {
+ // This could happen when multiple IPs are used
+ // Calling connect() again will reset the connection attempt and cause
+ // an error. Better to just close the socket and move on.
+ sockares.socket.connect_in_progress = false;
+ sockares.socket.m_Handle.Dispose ();
+ sockares.socket.m_Handle = new SafeSocketHandle (sockares.socket.Socket_internal (sockares.socket.addressFamily, sockares.socket.socketType, sockares.socket.protocolType, out error), true);
+ if (error != 0)
+ throw new SocketException (error);
+ }
+
+ bool blk = sockares.socket.is_blocking;
+ if (blk)
+ sockares.socket.Blocking = false;
+ Connect_internal (sockares.socket.m_Handle, remoteEP.Serialize (), out error, false);
+ if (blk)
+ sockares.socket.Blocking = true;
+
+ if (error == 0) {
+ // succeeded synch
+ sockares.socket.is_connected = true;
+ sockares.socket.is_bound = true;
+ sockares.Complete (true);
+ return;
+ }
+
+ if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
+ // error synch
+ sockares.socket.is_connected = false;
+ sockares.socket.is_bound = false;
+ sockares.Complete (new SocketException (error), true);
+ return;
+ }
+
+ // continue asynch
+ sockares.socket.is_connected = false;
+ sockares.socket.is_bound = false;
+ sockares.socket.connect_in_progress = true;
+
+ IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
}
static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
return;
}
- SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
- bool is_mconnect = mconnect != null && mconnect.Addresses != null;
-
try {
- EndPoint ep = sockares.EndPoint;
- int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
-
- if (error_code == 0) {
- if (is_mconnect)
- sockares = mconnect;
+ int error = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
- sockares.socket.seed_endpoint = ep;
+ if (error == 0) {
+ sockares.socket.seed_endpoint = sockares.EndPoint;
sockares.socket.is_connected = true;
sockares.socket.is_bound = true;
sockares.socket.connect_in_progress = false;
return;
}
- if (!is_mconnect) {
+ if (sockares.Addresses == null) {
sockares.socket.connect_in_progress = false;
- sockares.Complete (new SocketException (error_code));
+ sockares.Complete (new SocketException (error));
return;
}
- if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
- mconnect.Complete (new SocketException (error_code));
+ if (sockares.CurrentAddress >= sockares.Addresses.Length) {
+ sockares.Complete (new SocketException (error));
return;
}
- mconnect.socket.BeginMConnect (mconnect);
+ BeginMConnect (sockares);
} catch (Exception e) {
sockares.socket.connect_in_progress = false;
-
- if (is_mconnect)
- sockares = mconnect;
-
sockares.Complete (e);
- return;
}
});
--- /dev/null
+//
+// HttpListenerWebSocketContext.platformnotsupported.cs
+//
+// Author:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright (c) 2017 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.
+//
+
+namespace System.Net.WebSockets
+{
+ public partial class HttpListenerWebSocketContext : System.Net.WebSockets.WebSocketContext
+ {
+ const string EXCEPTION_MESSAGE = "System.Net.WebSockets.HttpListenerWebSocketContext is not supported on the current platform.";
+
+ private HttpListenerWebSocketContext() { }
+ public override System.Net.CookieCollection CookieCollection { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override System.Collections.Specialized.NameValueCollection Headers { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override bool IsAuthenticated { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override bool IsLocal { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override bool IsSecureConnection { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override string Origin { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override System.Uri RequestUri { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override string SecWebSocketKey { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override System.Collections.Generic.IEnumerable<string> SecWebSocketProtocols { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override string SecWebSocketVersion { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override System.Security.Principal.IPrincipal User { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ public override System.Net.WebSockets.WebSocket WebSocket { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } }
+ }
+}
\ No newline at end of file
ReferenceSources/SecureStringHelper.cs
ReferenceSources/Socket.cs
ReferenceSources/SR.cs
+ReferenceSources/SR2.cs
ReferenceSources/SRCategoryAttribute.cs
ReferenceSources/Win32Exception.cs
../../../external/corefx/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs
../../../external/corefx/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
-../../../external/corefx/src/System.Net.HttpListener/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs
-
../../../external/corefx/src/System.Private.Uri/src/System/UriBuilder.cs
../../../external/corefx/src/System.Runtime.Extensions/src/System/CodeDom/Compiler/IndentedTextWriter.cs
../referencesource/System/net/System/Net/Sockets/TCPClient.cs
../referencesource/System/net/System/Net/Sockets/TCPListener.cs
../referencesource/System/net/System/Net/Sockets/UDPClient.cs
+
+../../../external/corefx/src/System.Net.HttpListener/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs
System.Net/HttpWebResponse.platformnotsupported.cs
System.Net/ServicePoint.platformnotsupported.cs
System.Net/ServicePointManager.platformnotsupported.cs
+System.Net.WebSockets/HttpListenerWebSocketContext.platformnotsupported.cs
../Mono.Security/Mono.Security.X509.Extensions/AuthorityKeyIdentifierExtension.cs
Mono.Net.Dns/SimpleResolverEventArgs.cs
ReferenceSources/BinaryCompatibility.cs
ReferenceSources/ConfigurationManagerInternalFactory.cs
-ReferenceSources/SR2.cs
../referencesource/System/misc/PrivilegedConfigurationManager.cs
+++ /dev/null
-thisdir = class/Xunit.NetCore.Extensions
-SUBDIRS =
-include ../../build/rules.make
-
-XUNIT_LIBS := xunit.core xunit.abstractions xunit.execution.desktop xunit.assert
-
-LIBRARY = Xunit.NetCore.Extensions.dll
-LIB_REFS = System System.Core Facades/System.Runtime.InteropServices.RuntimeInformation Facades/System.Runtime Facades/System.Threading.Tasks
-LIB_MCS_FLAGS = $(patsubst %,-r:$(topdir)/../external/xunit-binaries/%.dll,$(XUNIT_LIBS))
-
-EXTRA_DISTFILES =
-
-NO_TEST = yes
-NO_INSTALL = yes
-NO_SIGN_ASSEMBLY = yes
-
-include ../../build/library.make
+++ /dev/null
-using System;
-using Xunit;
-using Xunit.Sdk;
-
-namespace Microsoft.Xunit.Performance
-{
- [TraitDiscoverer("Microsoft.Xunit.Performance.BenchmarkDiscoverer", "Xunit.NetCore.Extensions")]
- [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
- public class BenchmarkAttribute : Attribute, ITraitAttribute
- {
- public long InnerIterationCount { get; set; }
- }
-}
+++ /dev/null
-using System.Collections.Generic;
-using Xunit.Sdk;
-using Xunit.Abstractions;
-
-namespace Xunit.NetCore.Extensions
-{
- public class BenchmarkDiscoverer : ITraitDiscoverer
- {
- public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
- {
- yield return new KeyValuePair<string, string>("Benchmark", "True");
- }
- }
-}
+++ /dev/null
-../../../external/buildtools/src/xunit.netcore.extensions/*.cs
-../../../external/buildtools/src/xunit.netcore.extensions/Attributes/*.cs
-../../../external/buildtools/src/xunit.netcore.extensions/Discoverers/*.cs
-
-Microsoft.Xunit.Performance/BenchmarkAttribute.cs
-Microsoft.Xunit.Performance/BenchmarkDiscover.cs
include ../../build/rules.make
-the_libdir = $(topdir)/class/lib/$(PROFILE)/
+the_libdir = $(topdir)/class/lib/$(PROFILE_DIRECTORY)/
CSC_DIR = $(dir $(CSC_LOCATION))
# The directory where the AOT images are stored
images_dir = $(the_libdir)
PROGRAM_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
+LOG_FILE = $(PROFILE_DIRECTORY)_aot.log
+
ifndef SKIP_AOT
profile_file:=$(wildcard $(topdir)/class/lib/build/csc.*.aotprofile)
ifdef PLATFORM_AOT_SUFFIX
$(mcs_aot_image): $(mcs_exe) $(mscorlib_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(mcs_aot_image) --debug $(mcs_exe) || cat $(PROFILE)_aot.log || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(mcs_aot_image) --debug $(mcs_exe) || cat $(LOG_FILE) || (cat $(LOG_FILE); exit 1)
$(csc_aot_image): $(csc_exe) $(mscorlib_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_aot_image) --debug $(csc_exe) || cat $(PROFILE)_aot.log || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_aot_image) --debug $(csc_exe) || cat $(LOG_FILE) || (cat $(LOG_FILE); exit 1)
$(mscorlib_aot_image): $(mscorlib_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg) --debug $(mscorlib_dll) || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg) --debug $(mscorlib_dll) || (cat $(LOG_FILE); exit 1)
$(csc_MC_image): $(csc_MC_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_MC_image) --debug $(csc_MC_dll) || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_MC_image) --debug $(csc_MC_dll) || (cat $(LOG_FILE); exit 1)
$(csc_MCS_image): $(csc_MCS_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_MCS_image) --debug $(csc_MCS_dll) || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_MCS_image) --debug $(csc_MCS_dll) || (cat $(LOG_FILE); exit 1)
$(csc_SRM_image): $(csc_SRM_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_SRM_image) --debug --apply-bindings=$(csc_exe).config $(csc_SRM_dll) || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_SRM_image) --debug --apply-bindings=$(csc_exe).config $(csc_SRM_dll) || (cat $(LOG_FILE); exit 1)
$(csc_SCI_image): $(csc_SCI_dll) $(runtime_dep)
- $(Q_AOT) MONO_PATH='$(the_libdir)' > $(PROFILE)_aot.log 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_SCI_image) --debug $(csc_SCI_dll) || (cat $(PROFILE)_aot.log; exit 1)
+ $(Q_AOT) MONO_PATH='$(the_libdir)' > $(LOG_FILE) 2>&1 $(RUNTIME) --aot=bind-to-runtime-version$(profile_arg),outfile=$(csc_SCI_image) --debug $(csc_SCI_dll) || (cat $(LOG_FILE); exit 1)
ifdef ENABLE_AOT
CSC_IMAGES = $(csc_aot_image) $(csc_SRM_image) $(csc_SCI_image) $(csc_MC_image) $(csc_MCS_image)
clean-local:
- -rm -f $(mscorlib_aot_image) $(mcs_aot_image) $(CSC_IMAGES) $(PROFILE)_aot.log
+ -rm -f $(mscorlib_aot_image) $(mcs_aot_image) $(CSC_IMAGES) $(LOG_FILE)
# AOT build profile to speed up build
ifeq ($(PROFILE),build)
namespace System.Diagnostics.Tracing
{
- public abstract class EventListener : IDisposable
+ public class EventListener : IDisposable
{
- protected EventListener ()
+ public EventListener ()
{
}
+ //public event System.EventHandler<EventSourceCreatedEventArgs> EventSourceCreated;
+ //public event System.EventHandler<EventWrittenEventArgs> EventWritten;
+
public static int EventSourceIndex(EventSource eventSource)
{
return 0;
{
}
- protected internal abstract void OnEventWritten (EventWrittenEventArgs eventData);
+ protected internal virtual void OnEventWritten (EventWrittenEventArgs eventData)
+ {
+ }
public virtual void Dispose()
{
}
internal FieldInfo RuntimeResolve () {
- return typeb.CreateType ().GetField (this);
+ // typeb.CreateType() populates this.handle
+ var type_handle = new RuntimeTypeHandle (typeb.CreateType () as RuntimeType);
+ return FieldInfo.GetFieldFromHandle (handle, type_handle);
}
public override Module Module {
+++ /dev/null
-//
-// System.Runtime.InteropServices.CALLCONV.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Serializable]
- public enum CALLCONV
- {
- CC_CDECL = 1,
- CC_PASCAL = 2,
- CC_MSCPASCAL = 2,
- CC_MACPASCAL = 3,
- CC_STDCALL = 4,
- CC_RESERVED = 5,
- CC_SYSCALL = 6,
- CC_MPWCDECL = 7,
- CC_MPWPASCAL = 8,
- CC_MAX = 9
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-// System.Runtime.InteropServices/DISPPARAMS.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2002 Ximian, Inc.
-
-using System;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct DISPPARAMS {
- public IntPtr rgvarg;
- public IntPtr rgdispidNamedArgs;
- public int cArgs;
- public int cNamedArgs;
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ELEMDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct ELEMDESC
- {
- public TYPEDESC tdesc;
- public DESCUNION desc;
-
- [ComVisible (false)]
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct DESCUNION
- {
- [FieldOffset (0)]
- public IDLDESC idldesc;
- [FieldOffset (0)]
- public PARAMDESC paramdesc;
- }
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-// System.Runtime.InteropServices/EXCEPINFO.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2002 Ximian, Inc.
-
-using System;
-
-#if !FULL_AOT_RUNTIME
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct EXCEPINFO {
- public short wCode;
- public short wReserved;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrSource;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrDescription;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrHelpFile;
- public int dwHelpContext;
- public IntPtr pvReserved;
- public IntPtr pfnDeferredFillIn;
- }
-}
-
-#endif
+++ /dev/null
-//
-// System.Runtime.InteropServices.FUNCDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential)]
- public struct FUNCDESC
- {
- public int memid;
- public IntPtr lprgscode;
- public IntPtr lprgelemdescParam;
- public FUNCKIND funckind;
- public INVOKEKIND invkind;
- public CALLCONV callconv;
- public short cParams;
- public short cParamsOpt;
- public short oVft;
- public short cScodes;
- public ELEMDESC elemdescFunc;
- public short wFuncFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.FUNCFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Flags, Serializable]
- public enum FUNCFLAGS
- {
- FUNCFLAG_FRESTRICTED = 1,
- FUNCFLAG_FSOURCE = 2,
- FUNCFLAG_FBINDABLE = 4,
- FUNCFLAG_FREQUESTEDIT = 8,
- FUNCFLAG_FDISPLAYBIND = 16,
- FUNCFLAG_FDEFAULTBIND = 32,
- FUNCFLAG_FHIDDEN = 64,
- FUNCFLAG_FUSESGETLASTERROR = 128,
- FUNCFLAG_FDEFAULTCOLLELEM = 256,
- FUNCFLAG_FUIDEFAULT = 512,
- FUNCFLAG_FNONBROWSABLE = 1024,
- FUNCFLAG_FREPLACEABLE = 2048,
- FUNCFLAG_FIMMEDIATEBIND = 4096
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.FUNCKIND.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Serializable]
- public enum FUNCKIND
- {
- FUNC_VIRTUAL = 0,
- FUNC_PUREVIRTUAL = 1,
- FUNC_NONVIRTUAL = 2,
- FUNC_STATIC = 3,
- FUNC_DISPATCH = 4
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.IDLDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct IDLDESC
- {
- public int dwReserved;
- public IDLFLAG wIDLFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.IDLFLAG.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Flags, Serializable]
- public enum IDLFLAG
- {
- IDLFLAG_NONE = 0,
- IDLFLAG_FIN = 1,
- IDLFLAG_FOUT = 2,
- IDLFLAG_FLCID = 4,
- IDLFLAG_FRETVAL = 8
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.IMPLTYPEFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Flags, Serializable]
- public enum IMPLTYPEFLAGS
- {
- IMPLTYPEFLAG_FDEFAULT = 1,
- IMPLTYPEFLAG_FSOURCE = 2,
- IMPLTYPEFLAG_FRESTRICTED = 4,
- IMPLTYPEFLAG_FDEFAULTVTABLE = 8
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-// System.Runtime.InteropServices/INVOKEKIND.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2002 Ximian, Inc.
-
-using System;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Serializable]
- public enum INVOKEKIND {
- INVOKE_FUNC = 1,
- INVOKE_PROPERTYGET = 2,
- INVOKE_PROPERTYPUT = 4,
- INVOKE_PROPERTYPUTREF = 8
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.PARAMDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct PARAMDESC
- {
- public IntPtr lpVarValue;
- public PARAMFLAG wParamFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.PARAMFLAG.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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;
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [Serializable]
- [Flags]
- public enum PARAMFLAG
- {
- PARAMFLAG_NONE = 0,
- PARAMFLAG_FIN = 1,
- PARAMFLAG_FOUT = 2,
- PARAMFLAG_FLCID = 4,
- PARAMFLAG_FRETVAL = 8,
- PARAMFLAG_FOPT = 16,
- PARAMFLAG_FHASDEFAULT = 32,
- PARAMFLAG_FHASCUSTDATA = 64
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.TYPEATTR.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct TYPEATTR
- {
- public const int MEMBER_ID_NIL = -1;
-
- public Guid guid;
- public int lcid;
- public int dwReserved;
- public int memidConstructor;
- public int memidDestructor;
- public IntPtr lpstrSchema;
- public int cbSizeInstance;
- public TYPEKIND typekind;
- public short cFuncs;
- public short cVars;
- public short cImplTypes;
- public short cbSizeVft;
- public short cbAlignment;
- public TYPEFLAGS wTypeFlags;
- public short wMajorVerNum;
- public short wMinorVerNum;
- public TYPEDESC tdescAlias;
- public IDLDESC idldescType;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.TYPEDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.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.
-//
-
-namespace System.Runtime.InteropServices
-{
- [Obsolete]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct TYPEDESC
- {
- public IntPtr lpValue;
- public short vt;
- }
-}
[Serializable]
internal class CADMethodRef
{
- internal string FullTypeName;
- internal IntPtr MethodHandlePtr;
+ Type[] GetTypes (string[] typeArray)
+ {
+ Type[] res = new Type [typeArray.Length];
+ for (int i = 0; i < typeArray.Length; ++i)
+ res [i] = Type.GetType (typeArray [i], true);
+ return res;
+ }
- public RuntimeMethodHandle MethodHandle {
- get {
- return new RuntimeMethodHandle (MethodHandlePtr);
- }
+ bool ctor;
+ string typeName;
+ string methodName;
+ string[] param_names;
+ string[] generic_arg_names;
+
+ public MethodBase Resolve ()
+ {
+ Type type = Type.GetType (typeName, true);
+ MethodBase sig_cand = null;
+ Type[] param_types = GetTypes (param_names);
+ if (ctor)
+ sig_cand = type.GetConstructor (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+ else
+ sig_cand = type.GetMethod (methodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+
+ if (sig_cand != null && generic_arg_names != null)
+ sig_cand = ((MethodInfo)sig_cand).MakeGenericMethod (GetTypes (generic_arg_names));
+
+ if (sig_cand == null)
+ throw new RemotingException ($"Method '{methodName}' not found in type '{typeName}'");
+
+ return sig_cand;
}
public CADMethodRef (IMethodMessage msg)
{
- MethodHandlePtr = msg.MethodBase.MethodHandle.Value;
- FullTypeName = msg.MethodBase.DeclaringType.AssemblyQualifiedName;
+ MethodBase method = msg.MethodBase;
+ typeName = method.DeclaringType.AssemblyQualifiedName;
+ ctor = method.IsConstructor;
+ methodName = method.Name;
+
+ if (!ctor && method.IsGenericMethod) {
+ var ga = method.GetGenericArguments ();
+ generic_arg_names = new string [ga.Length];
+ for (int i = 0; i < ga.Length; ++i)
+ generic_arg_names [i] = ga [i].AssemblyQualifiedName;
+
+ method = ((MethodInfo)method).GetGenericMethodDefinition ();
+ }
+
+ var param_types = method.GetParameters ();
+ param_names = new string [param_types.Length];
+ for (int i = 0; i < param_types.Length; ++i)
+ param_names [i] = param_types [i].ParameterType.AssemblyQualifiedName;
}
}
serializedMethod = CADSerializer.SerializeObject (methodRef).GetBuffer ();
}
- internal MethodBase method {
- get { return GetMethod (); }
- }
-
internal MethodBase GetMethod ()
{
CADMethodRef methRef = (CADMethodRef)CADSerializer.DeserializeObjectSafe (serializedMethod);
- MethodBase _method;
-
- Type tt = Type.GetType (methRef.FullTypeName, true);
- if (tt.IsGenericType || tt.IsGenericTypeDefinition) {
- _method = MethodBase.GetMethodFromHandleNoGenericCheck (methRef.MethodHandle);
- } else {
- _method = MethodBase.GetMethodFromHandle (methRef.MethodHandle);
- }
-
- if (tt != _method.DeclaringType) {
- // The target domain has loaded the type from a different assembly.
- // We need to locate the correct type and get the method from it
- Type [] signature = GetSignature (_method, true);
- if (_method.IsGenericMethod) {
- MethodBase [] methods = tt.GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
- Type [] base_args = _method.GetGenericArguments ();
- foreach (MethodBase method in methods) {
- if (!method.IsGenericMethod || method.Name != _method.Name)
- continue;
- Type [] method_args = method.GetGenericArguments ();
- if (base_args.Length != method_args.Length)
- continue;
-
- MethodInfo method_instance = ((MethodInfo) method).MakeGenericMethod (base_args);
- Type [] base_sig = GetSignature (method_instance, false);
- if (base_sig.Length != signature.Length) {
- continue;
- }
- bool dont = false;
- for (int i = base_sig.Length - 1; i >= 0; i--) {
- if (base_sig [i] != signature [i]) {
- dont = true;
- break;
- }
- }
- if (dont)
- continue;
- return method_instance;
- }
- return _method;
- }
-
- MethodBase mb = tt.GetMethod (_method.Name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, signature, null);
- if (mb == null)
- throw new RemotingException ("Method '" + _method.Name + "' not found in type '" + tt + "'");
- return mb;
- }
- return _method;
+ return methRef.Resolve ();
}
static protected Type [] GetSignature (MethodBase methodBase, bool load)
}
return signature;
}
+
// Helper to marshal properties
internal static int MarshalProperties (IDictionary dict, ref ArrayList args) {
IDictionary serDict = dict;
_returnValue = MarshalArgument ( retMsg.ReturnValue, ref serializeList);
_args = MarshalArguments ( retMsg.Args, ref serializeList);
- _sig = GetSignature (method, true);
+ _sig = GetSignature (GetMethod (), true);
if (null != retMsg.Exception) {
if (null == serializeList)
//
namespace System.Security.AccessControl {
- public enum AceType {
+ public enum AceType : byte {
AccessAllowed = 0,
AccessDenied = 1,
SystemAudit = 2,
[Serializable]
[ComVisible (true)]
- public class PolicyException : SystemException, _Exception {
+ public class PolicyException : SystemException {
// Constructors
public PolicyException ()
: base (Locale.GetText ("Cannot run because of policy."))
Assert.AreSame (buildX, defX);
}
+
+ [Test]
+ public void FieldsWithSameName () {
+ // Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=57222
+ string fileName = CreateTempAssembly ();
+
+ var assemblyName = new AssemblyName { Name = "test" };
+ var dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave);
+ var dynamicModule = dynamicAssembly.DefineDynamicModule (assemblyName.Name, fileName);
+ var typeBuilder = dynamicModule.DefineType ("type1", TypeAttributes.Public | TypeAttributes.Class);
+
+ var mainMethod = typeBuilder.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (int), new Type[0]);
+ var mainMethodIl = mainMethod.GetILGenerator ();
+
+ var f1 = typeBuilder.DefineField ("x", typeof (byte), FieldAttributes.Private | FieldAttributes.Static);
+ var f2 = typeBuilder.DefineField ("x", typeof (sbyte), FieldAttributes.Private | FieldAttributes.Static);
+
+ mainMethodIl.Emit (OpCodes.Ldsflda, f1);
+ mainMethodIl.Emit (OpCodes.Ldsflda, f2);
+ mainMethodIl.Emit (OpCodes.Pop);
+ mainMethodIl.Emit (OpCodes.Pop);
+ mainMethodIl.Emit (OpCodes.Ldc_I4_0);
+ mainMethodIl.Emit (OpCodes.Ret);
+
+ typeBuilder.CreateType ();
+ dynamicAssembly.SetEntryPoint (mainMethod);
+
+ dynamicAssembly.Save (fileName);
+ }
+ [Test]
+ public void FieldsWithSameNameAndType () {
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=57222
+ string fileName = CreateTempAssembly ();
+
+ var assemblyName = new AssemblyName { Name = "test" };
+ var dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave);
+ var dynamicModule = dynamicAssembly.DefineDynamicModule (assemblyName.Name, fileName);
+ var typeBuilder = dynamicModule.DefineType ("type1", TypeAttributes.Public | TypeAttributes.Class);
+
+ var mainMethod = typeBuilder.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (int), new Type[0]);
+ var mainMethodIl = mainMethod.GetILGenerator ();
+
+ var f1 = typeBuilder.DefineField ("x", typeof (sbyte), FieldAttributes.Private | FieldAttributes.Static);
+ var f2 = typeBuilder.DefineField ("x", typeof (sbyte), FieldAttributes.Private | FieldAttributes.Static);
+
+ mainMethodIl.Emit (OpCodes.Ldsflda, f1);
+ mainMethodIl.Emit (OpCodes.Ldsflda, f2);
+ mainMethodIl.Emit (OpCodes.Pop);
+ mainMethodIl.Emit (OpCodes.Pop);
+ mainMethodIl.Emit (OpCodes.Ldc_I4_0);
+ mainMethodIl.Emit (OpCodes.Ret);
+
+ typeBuilder.CreateType ();
+ dynamicAssembly.SetEntryPoint (mainMethod);
+
+ dynamicAssembly.Save (fileName);
+ }
+
+ [Test]
+ public void MethodsWithSameNameAndSig () {
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=57222
+ string fileName = CreateTempAssembly ();
+
+ var assemblyName = new AssemblyName { Name = "test" };
+ var dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave);
+ var dynamicModule = dynamicAssembly.DefineDynamicModule (assemblyName.Name, fileName);
+ var typeBuilder = dynamicModule.DefineType ("type1", TypeAttributes.Public | TypeAttributes.Class);
+
+ var mainMethod = typeBuilder.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (int), new Type[0]);
+ var mainMethodIl = mainMethod.GetILGenerator ();
+
+ var m1 = typeBuilder.DefineMethod ("X", MethodAttributes.Private | MethodAttributes.Static, typeof (void), new Type [0]);
+ var m2 = typeBuilder.DefineMethod ("X", MethodAttributes.Private | MethodAttributes.Static, typeof (void), new Type [0]);
+ m1.GetILGenerator ().Emit (OpCodes.Ret);
+ m2.GetILGenerator ().Emit (OpCodes.Ret);
+
+ mainMethodIl.Emit (OpCodes.Call, m1);
+ mainMethodIl.Emit (OpCodes.Call, m2);
+ mainMethodIl.Emit (OpCodes.Ldc_I4_0);
+ mainMethodIl.Emit (OpCodes.Ret);
+
+ typeBuilder.CreateType ();
+ dynamicAssembly.SetEntryPoint (mainMethod);
+
+ dynamicAssembly.Save (fileName);
+ }
}
}
}
}
#endif // MONO_FEATURE_THREAD_SUSPEND_RESUME
+
+ [Test]
+ public static void SignalAndWait()
+ {
+ using (var eventToSignal = new AutoResetEvent (false))
+ using (var eventToWait = new AutoResetEvent (false))
+ {
+ eventToWait.Set ();
+
+ Assert.IsTrue (WaitHandle.SignalAndWait (eventToSignal, eventToWait), "#1");
+ Assert.IsTrue (eventToSignal.WaitOne (), "#2");
+ }
+ }
}
}
<Compile Include="..\..\..\external\corefx\src\System.Collections.Concurrent\src\System\Collections\Concurrent\OrderablePartitioner.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Collections.Concurrent\src\System\Collections\Concurrent\Partitioner.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Collections.Concurrent\src\System\Collections\Concurrent\PartitionerStatic.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Collections\src\System\Collections\Generic\CollectionExtensions.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Security.Cryptography.X509Certificates\src\System\Security\Cryptography\X509Certificates\X509ContentType.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Security.Cryptography.X509Certificates\src\System\Security\Cryptography\X509Certificates\X509KeyStorageFlags.cs" />\r
<Compile Include="..\..\..\external\corert\src\Common\src\Interop\Unix\Interop.Libraries.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Collections\Generic\KeyValuePair.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Diagnostics\Debug.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\IO\Win32Marshal.cs" />\r
+ <Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Runtime\CompilerServices\IsByRefLikeAttribute.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Runtime\CompilerServices\IsReadOnlyAttribute.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Runtime\CompilerServices\ITuple.cs" />\r
<Compile Include="..\..\..\external\corert\src\System.Private.CoreLib\shared\System\Runtime\CompilerServices\RuntimeFeature.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\pointer.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\propertyattributes.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\reflectioncontext.cs" />\r
+ <Compile Include="..\referencesource\mscorlib\system\reflection\reflectiontypeloadexception.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\resourceattributes.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\RuntimeReflectionExtensions.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\reflection\targetexception.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\safehandle.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\sehexception.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\ucomienumconnections.cs" />\r
+ <Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\ucomitypeinfo.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\unknownwrapper.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\variantWrapper.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\runtime\interopservices\windowsruntime\attributes.cs" />\r
<Compile Include="System.Reflection\ParameterInfo.cs" />\r
<Compile Include="System.Reflection\PortableExecutableKinds.cs" />\r
<Compile Include="System.Reflection\PropertyInfo.cs" />\r
- <Compile Include="System.Reflection\ReflectionTypeLoadException.cs" />\r
<Compile Include="System.Reflection\StrongNameKeyPair.cs" />\r
<Compile Include="System.Resources\Win32Resources.cs" />\r
<Compile Include="System.Runtime.CompilerServices\ConditionalWeakTable.cs" />\r
<Compile Include="System.Runtime.InteropServices\_TypeBuilder.cs" />\r
<Compile Include="System.Runtime.InteropServices\BIND_OPTS.cs" />\r
<Compile Include="System.Runtime.InteropServices\BINDPTR.cs" />\r
- <Compile Include="System.Runtime.InteropServices\CALLCONV.cs" />\r
<Compile Include="System.Runtime.InteropServices\ComEventsHelper.cs" />\r
<Compile Include="System.Runtime.InteropServices\CustomQueryInterfaceMode.cs" />\r
<Compile Include="System.Runtime.InteropServices\DESCKIND.cs" />\r
- <Compile Include="System.Runtime.InteropServices\DISPPARAMS.cs" />\r
- <Compile Include="System.Runtime.InteropServices\ELEMDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\EXCEPINFO.cs" />\r
<Compile Include="System.Runtime.InteropServices\ExporterEventKind.cs" />\r
<Compile Include="System.Runtime.InteropServices\ExtensibleClassFactory.cs" />\r
<Compile Include="System.Runtime.InteropServices\FILETIME.cs" />\r
- <Compile Include="System.Runtime.InteropServices\FUNCDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\FUNCFLAGS.cs" />\r
- <Compile Include="System.Runtime.InteropServices\FUNCKIND.cs" />\r
<Compile Include="System.Runtime.InteropServices\GCHandle.cs" />\r
<Compile Include="System.Runtime.InteropServices\GCHandleType.cs" />\r
- <Compile Include="System.Runtime.InteropServices\IDLDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\IDLFLAG.cs" />\r
<Compile Include="System.Runtime.InteropServices\IErrorInfo.cs" />\r
- <Compile Include="System.Runtime.InteropServices\IMPLTYPEFLAGS.cs" />\r
<Compile Include="System.Runtime.InteropServices\ImporterEventKind.cs" />\r
- <Compile Include="System.Runtime.InteropServices\INVOKEKIND.cs" />\r
<Compile Include="System.Runtime.InteropServices\ITypeLibConverter.cs" />\r
<Compile Include="System.Runtime.InteropServices\ITypeLibExporterNameProvider.cs" />\r
<Compile Include="System.Runtime.InteropServices\ITypeLibExporterNotifySink.cs" />\r
<Compile Include="System.Runtime.InteropServices\ManagedErrorInfo.cs" />\r
<Compile Include="System.Runtime.InteropServices\Marshal.cs" />\r
<Compile Include="System.Runtime.InteropServices\MarshalAsAttribute.cs" />\r
- <Compile Include="System.Runtime.InteropServices\PARAMDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\PARAMFLAG.cs" />\r
<Compile Include="System.Runtime.InteropServices\RegistrationClassContext.cs" />\r
<Compile Include="System.Runtime.InteropServices\RegistrationConnectionType.cs" />\r
<Compile Include="System.Runtime.InteropServices\RegistrationServices.cs" />\r
<Compile Include="System.Runtime.InteropServices\SafeHandle.cs" />\r
<Compile Include="System.Runtime.InteropServices\STATSTG.cs" />\r
<Compile Include="System.Runtime.InteropServices\SYSKIND.cs" />\r
- <Compile Include="System.Runtime.InteropServices\TYPEATTR.cs" />\r
- <Compile Include="System.Runtime.InteropServices\TYPEDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\TYPEFLAGS.cs" />\r
- <Compile Include="System.Runtime.InteropServices\TYPEKIND.cs" />\r
<Compile Include="System.Runtime.InteropServices\TYPELIBATTR.cs" />\r
<Compile Include="System.Runtime.InteropServices\TypeLibConverter.cs" />\r
<Compile Include="System.Runtime.InteropServices\TypeLibExporterFlags.cs" />\r
<Compile Include="System.Runtime.InteropServices\UCOMIRunningObjectTable.cs" />\r
<Compile Include="System.Runtime.InteropServices\UCOMIStream.cs" />\r
<Compile Include="System.Runtime.InteropServices\UCOMITypeComp.cs" />\r
- <Compile Include="System.Runtime.InteropServices\UCOMITypeInfo.cs" />\r
<Compile Include="System.Runtime.InteropServices\UCOMITypeLib.cs" />\r
- <Compile Include="System.Runtime.InteropServices\VARDESC.cs" />\r
- <Compile Include="System.Runtime.InteropServices\VARFLAGS.cs" />\r
<Compile Include="System.Runtime.Remoting.Activation\ActivationServices.cs" />\r
<Compile Include="System.Runtime.Remoting.Activation\ActivatorLevel.cs" />\r
<Compile Include="System.Runtime.Remoting.Activation\AppDomainLevelActivator.cs" />\r
<EmbeddedResource Include="resources/collation.cjkKOlv2.bin">\r
<LogicalName>collation.cjkKOlv2.bin</LogicalName>\r
</EmbeddedResource>\r
+ <EmbeddedResource Include="LinkerDescriptor/mscorlib.xml">\r
+ <LogicalName>mscorlib.xml</LogicalName>\r
+ </EmbeddedResource>\r
</ItemGroup>\r
</Project>\r
System.Reflection/ParameterInfo.cs
System.Reflection/PortableExecutableKinds.cs
System.Reflection/PropertyInfo.cs
-System.Reflection/ReflectionTypeLoadException.cs
System.Reflection/StrongNameKeyPair.cs
System.Reflection.Emit/AssemblyBuilder.cs
System.Reflection.Emit/AssemblyBuilderAccess.cs
System.Runtime.InteropServices/_TypeBuilder.cs
System.Runtime.InteropServices/BIND_OPTS.cs
System.Runtime.InteropServices/BINDPTR.cs
-System.Runtime.InteropServices/CALLCONV.cs
System.Runtime.InteropServices/DESCKIND.cs
-System.Runtime.InteropServices/DISPPARAMS.cs
-System.Runtime.InteropServices/ELEMDESC.cs
-System.Runtime.InteropServices/EXCEPINFO.cs
System.Runtime.InteropServices/ExporterEventKind.cs
System.Runtime.InteropServices/ExtensibleClassFactory.cs
System.Runtime.InteropServices/FILETIME.cs
-System.Runtime.InteropServices/FUNCDESC.cs
-System.Runtime.InteropServices/FUNCFLAGS.cs
-System.Runtime.InteropServices/FUNCKIND.cs
System.Runtime.InteropServices/GCHandle.cs
System.Runtime.InteropServices/GCHandleType.cs
-System.Runtime.InteropServices/IDLDESC.cs
-System.Runtime.InteropServices/IDLFLAG.cs
System.Runtime.InteropServices/IErrorInfo.cs
-System.Runtime.InteropServices/IMPLTYPEFLAGS.cs
-System.Runtime.InteropServices/INVOKEKIND.cs
System.Runtime.InteropServices/ITypeLibConverter.cs
System.Runtime.InteropServices/ITypeLibExporterNameProvider.cs
System.Runtime.InteropServices/ITypeLibExporterNotifySink.cs
System.Runtime.InteropServices/ManagedErrorInfo.cs
System.Runtime.InteropServices/Marshal.cs
System.Runtime.InteropServices/MarshalAsAttribute.cs
-System.Runtime.InteropServices/PARAMDESC.cs
-System.Runtime.InteropServices/PARAMFLAG.cs
System.Runtime.InteropServices/RegistrationClassContext.cs
System.Runtime.InteropServices/RegistrationConnectionType.cs
System.Runtime.InteropServices/STATSTG.cs
System.Runtime.InteropServices/SafeBuffer.cs
System.Runtime.InteropServices/SafeHandle.cs
System.Runtime.InteropServices/SYSKIND.cs
-System.Runtime.InteropServices/TYPEATTR.cs
-System.Runtime.InteropServices/TYPEDESC.cs
-System.Runtime.InteropServices/TYPEFLAGS.cs
-System.Runtime.InteropServices/TYPEKIND.cs
System.Runtime.InteropServices/TYPELIBATTR.cs
System.Runtime.InteropServices/TypeLibConverter.cs
System.Runtime.InteropServices/TypeLibExporterFlags.cs
System.Runtime.InteropServices/UCOMIRunningObjectTable.cs
System.Runtime.InteropServices/UCOMIStream.cs
System.Runtime.InteropServices/UCOMITypeComp.cs
-System.Runtime.InteropServices/UCOMITypeInfo.cs
System.Runtime.InteropServices/UCOMITypeLib.cs
-System.Runtime.InteropServices/VARDESC.cs
-System.Runtime.InteropServices/VARFLAGS.cs
System.Runtime.InteropServices/CustomQueryInterfaceMode.cs
System.Runtime.InteropServices/ComEventsHelper.cs
../referencesource/mscorlib/system/reflection/pointer.cs
../referencesource/mscorlib/system/reflection/propertyattributes.cs
../referencesource/mscorlib/system/reflection/reflectioncontext.cs
+../referencesource/mscorlib/system/reflection/reflectiontypeloadexception.cs
../referencesource/mscorlib/system/reflection/resourceattributes.cs
../referencesource/mscorlib/system/reflection/RuntimeReflectionExtensions.cs
../referencesource/mscorlib/system/reflection/targetexception.cs
../referencesource/mscorlib/system/runtime/interopservices/safearraytypemismatchexception.cs
../referencesource/mscorlib/system/runtime/interopservices/safehandle.cs
../referencesource/mscorlib/system/runtime/interopservices/sehexception.cs
+../referencesource/mscorlib/system/runtime/interopservices/ucomitypeinfo.cs
../referencesource/mscorlib/system/runtime/interopservices/ucomienumconnections.cs
../referencesource/mscorlib/system/runtime/interopservices/unknownwrapper.cs
../referencesource/mscorlib/system/runtime/interopservices/variantWrapper.cs
../../../external/corert/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.cs
../../../external/corert/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsReadOnlyAttribute.cs
+../../../external/corert/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsByRefLikeAttribute.cs
../../../external/corert/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ITuple.cs
../../../external/corert/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs
../../../external/corert/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs
corefx/SR.cs
+../../../external/corefx/src/System.Collections/src/System/Collections/Generic/CollectionExtensions.cs
+
../../../external/corefx/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs
../../../external/corefx/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
../../../external/corefx/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs
VARFLAG_FIMMEDIATEBIND =0x1000
}
+#if !FULL_AOT_RUNTIME
[Obsolete("Use System.Runtime.InteropServices.ComTypes.ITypeInfo instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
[Guid("00020401-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
void ReleaseFuncDesc(IntPtr pFuncDesc);
void ReleaseVarDesc(IntPtr pVarDesc);
}
+#endif
}
--- /dev/null
+// CS0019: Operator `??' cannot be applied to operands of type `void' and `throw expression'
+// Line: 20
+
+class C
+{
+ public static void Main ()
+ {
+ var s = Main () ?? throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0128: A local variable named `x' is already defined in this scope
+// Line: 9
+
+class X
+{
+ public static void Main ()
+ {
+ Foo (out int x);
+ Foo (out int x);
+ }
+
+ static void Foo (out int arg)
+ {
+ arg = 2;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0128: A local variable named `s' is already defined in this scope
+// Line: 12
+
+class C
+{
+ public static void Main ()
+ {
+ object o = null;
+
+ var x1 = o is string s;
+ var x2 = o is string s;
+ }
+}
--- /dev/null
+// CS0136: A local variable named `s' cannot be declared in this scope because it would give a different meaning to `s', which is already used in a `parent or current' scope to denote something else
+// Line: 10
+
+internal class Program
+{
+ public static void Main ()
+ {
+ object o = null;
+ if (o is string s) {
+ int s = 1;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0155: The type caught or thrown must be derived from System.Exception
+// Line: 9
+
+class X
+{
+ public int Test () => throw "";
+}
--- /dev/null
+// CS0162: Unreachable code detected
+// Line: 12
+// Compiler options: -warnaserror -warn:2
+
+using System;
+
+class X
+{
+ void Test ()
+ {
+ var x = true ? throw new NullReferenceException () : 1;
+ x = 2;
+ return;
+ }
+
+ static void Main ()
+ {
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `s'
+// Line: 12
+
+class X
+{
+ static string Foo (object arg)
+ {
+ if (arg is string s) {
+
+ }
+
+ return s;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between `throw expression' and `throw expression'
+// Line: 8
+
+class C
+{
+ public static void Test (bool b)
+ {
+ var s = b ? throw null : throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0411: The type arguments for method `C.Foo<T>(System.Func<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
+// Line: 10
+
+using System;
+
+public class C
+{
+ public static void Main ()
+ {
+ Foo (() => throw null);
+ }
+
+ static void Foo<T> (Func<T> arg)
+ {
+ }
+}
\ No newline at end of file
+++ /dev/null
-// CS0815: An implicitly typed local variable declaration cannot be initialized with `void'
-// Line: 8
-// Compiler options: -langversion:experimental
-
-class X
-{
- public static void Main ()
- {
- Foo (out var x = Main ());
- }
-
- static void Foo (out int i)
- {
- i = 0;
- }
-}
\ No newline at end of file
-// CS1061: Type `int' does not contain a definition for `GetValueOrDefault' and no extension method `GetValueOrDefault' of type `int' could be found. Are you missing an assembly reference?
+// CS1061: Type `int' does not contain a definition for `GetValueOrDefault' and no extension method `GetValueOrDefault' of type `int' could be found. Are you missing `System.Collections.Generic' using directive?
// Line: 9
class C
+++ /dev/null
-// CS1501: Argument `#1' cannot convert `ref string' expression to type `ref int'
-// Line: 8
-// Compiler options: -langversion:experimental
-
-class C
-{
- public static void Main ()
- {
- Foo (ref var x = "");
- }
-
- static void Foo (ref int i)
- {
- }
-}
\ No newline at end of file
-// CS1617: Invalid -langversion option `ISO'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 6
+// CS1617: Invalid -langversion option `ISO'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 7
// Line: 0
// Compiler options: -langversion:ISO
-// CS1644: Feature `declaration expression' cannot be used because it is not part of the C# 5.0 language specification
-// Line: 12
+// CS1644: Feature `out variable declaration' cannot be used because it is not part of the C# 5.0 language specification
+// Line: 9
// Compiler options: -langversion:5
class C
--- /dev/null
+// CS1644: Feature `throw expression' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 5
+// Compiler options: -langversion:6
+
+static class Class
+{
+ int Prop => throw null;
+}
--- /dev/null
+// CS1644: Feature `pattern matching' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 9
+// Compiler options: -langversion:6
+
+class Class
+{
+ static void Foo (object arg)
+ {
+ if (arg is Type v) {
+ return;
+ }
+ }
+}
+++ /dev/null
-// CS8046: An expression tree cannot contain a declaration expression
-// Line: 11
-// Compiler options: -langversion:experimental
-
-using System;
-using System.Linq.Expressions;
-
-class C
-{
- static void Main()
- {
- Expression<Func<bool>> e = () => Out (out int x);
- }
-
- static bool Out (out int value)
- {
- value = 3;
- return true;
- }
-}
\ No newline at end of file
+++ /dev/null
-// CS8047: Declaration expression cannot be used in this context
-// Line: 8
-// Compiler options: -langversion:experimental
-
-public class C
-{
- public static void Main ()
- {
- dynamic target = 3;
- var x = new Test (target, out var y);
- }
-}
-
-class Test
-{
- public Test (int x, out int y)
- {
- y = 0;
- }
-}
\ No newline at end of file
--- /dev/null
+// CS8116: The nullable type `byte?' pattern matching is not allowed. Consider using underlying type `byte'
+// Line: 11
+
+using System;
+
+class C
+{
+ public static void Main ()
+ {
+ object o2 = null;
+ bool r2 = o2 is Nullable<byte> t3;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8117: Cannot use null as pattern matching operand
+// Line: 8
+
+class C
+{
+ static object Test ()
+ {
+ return null is object res;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8122: An expression tree cannot contain a pattern matching operator
+// Line: 12
+
+using System;
+using System.Linq.Expressions;
+
+class X
+{
+ public static void Main ()
+ {
+ object o = 1;
+ Expression<Func<bool>> e = () => o is int y;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8188: An expression tree cannot not contain a throw expression
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+ public static void Main ()
+ {
+ Expression<Func<object>> l = () => throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8196: Reference to an implicitly typed out variable `x1' is not permitted in the same argument list
+// Line: 8
+
+public class C
+{
+ public static void Main ()
+ {
+ Test (out var x1, out x1);
+ }
+
+ static void Test (out int x, out int x2)
+ {
+ x = 1;
+ x2 = 2;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8196: Reference to an implicitly typed out variable `x1' is not permitted in the same argument list
+// Line: 8
+
+public class C
+{
+ public static void Main ()
+ {
+ Test (out var x1, out x1);
+ }
+
+ static void Test (out int x, out int x2)
+ {
+ x = 1;
+ x2 = 2;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8197: Cannot infer the type of implicitly-typed out variable `y'
+// Line: 9
+
+public class C
+{
+ public static void Main ()
+ {
+ dynamic target = 3;
+ var x = new Test (target, out var y);
+ }
+}
+
+class Test
+{
+ public Test (int x, out int y)
+ {
+ y = 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8198: An expression tree cannot contain out variable declaration
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+ static void Main()
+ {
+ Expression<Func<bool>> e = () => Out (out int x);
+ }
+
+ static bool Out (out int value)
+ {
+ value = 3;
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 6
+
+public class C
+{
+ bool res = Foo (out int arg);
+
+ static bool Foo (out int arg)
+ {
+ arg = 2;
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 11
+
+public class C
+{
+ bool Prop { get; } = Foo (out int arg);
+
+ static bool Foo (out int arg)
+ {
+ arg = 2;
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 8
+
+using System;
+
+public class C
+{
+ event Action H = Foo (out var res);
+
+ static Action Foo (out int arg)
+ {
+ arg = 2;
+ return null;
+ }
+}
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 6
+
+public class C
+{
+ bool res = Foo () is string s;
+
+ static object Foo ()
+ {
+ return null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 6
+
+class X
+{
+ public static bool Test { get; } = Foo () is bool x;
+
+ static object Foo ()
+ {
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers
+// Line: 11
+
+public class C
+{
+ public C (bool value)
+ {
+ }
+
+ public C ()
+ : this (Foo (out int arg))
+ {
+ }
+
+ static bool Foo (out int arg)
+ {
+ arg = 2;
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8201: Out variable and pattern variable declarations are not allowed within a query clause
+// Line: 11
+
+using System.Linq;
+
+class Program
+{
+ public static void Main ()
+ {
+ var a = "abcdef";
+ var res = from x in a from y in M (a, out var z) select x;
+ }
+
+ public static T M<T>(T x, out T z) => z = x;
+}
\ No newline at end of file
--- /dev/null
+// CS8208: The type `dynamic' pattern matching is not allowed
+// Line: 9
+
+static class Program
+{
+ public static void Main ()
+ {
+ object o = null;
+ if (o is dynamic res) {
+ }
+ }
+}
fc.TryFinally = prev_tf;
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
block.MarkReachable (rc);
+ return rc;
}
public void SetHasThisAccess ()
//
// Returns dynamic when at least one argument is of dynamic type
//
- public void Resolve (ResolveContext ec, out bool dynamic)
+ public void Resolve (ResolveContext rc, out bool dynamic)
{
dynamic = false;
+
+ List<LocalVariable> var_locals = null;
foreach (Argument a in args) {
- a.Resolve (ec);
- if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef)
+ a.Resolve (rc);
+
+ if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) {
dynamic = true;
+ continue;
+ }
+
+ if (a.Type == InternalType.VarOutType) {
+ var de = a.Expr as DeclarationExpression;
+ if (de != null) {
+ if (var_locals == null)
+ var_locals = new List<LocalVariable> ();
+
+ var_locals.Add (de.Variable);
+ continue;
+ }
+
+ var lvr = a.Expr as LocalVariableReference;
+ if (lvr != null && var_locals != null && var_locals.Contains (lvr.local_info)) {
+ rc.Report.Error (8196, lvr.Location, "Reference to an implicitly typed out variable `{0}' is not permitted in the same argument list", lvr.Name);
+ lvr.Type = InternalType.ErrorType;
+ }
+ }
}
}
}
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
- var es = source as ExpressionStatement;
- if (es != null)
- es.MarkReachable (rc);
+ return source.MarkReachable (rc);
}
}
stmt.EmitStatement (ec);
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
- base.MarkReachable (rc);
- stmt.MarkReachable (rc);
+ return stmt.MarkReachable (rc);
}
public override object Accept (StructuralVisitor visitor)
ec.Emit (OpCodes.Ret);
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
//
// Reachability has been done in AsyncInitializerStatement
//
+ return rc;
}
}
//
lc = left as EnumConstant;
rc = right as EnumConstant;
- if (lc != null || rc != null){
+ if (lc != null || rc != null) {
+ TypeSpec res_type;
if (lc == null) {
- lc = rc;
- lt = lc.Type;
- right = left;
- }
+ res_type = right.Type;
- // U has to be implicitly convetible to E.base
- right = right.ConvertImplicitly (lc.Child.Type);
- if (right == null)
- return null;
+ // Y has to be implicitly convertible to E.base
+ left = left.ConvertImplicitly (rc.Child.Type);
+ if (left == null)
+ return null;
- result = BinaryFold (ec, oper, lc.Child, right, loc);
+ right = rc.Child;
+ } else {
+ res_type = left.Type;
+
+ // U has to be implicitly convertible to E.base
+ right = right.ConvertImplicitly (lc.Child.Type);
+ if (right == null)
+ return null;
+
+ left = lc.Child;
+ }
+
+ result = BinaryFold (ec, oper, left, right, loc);
if (result == null)
return null;
- result = result.Reduce (ec, lt);
+ result = result.Reduce (ec, res_type);
if (result == null)
return null;
- return new EnumConstant (result, lt);
+ return new EnumConstant (result, res_type);
}
if (left is NullLiteral && right is NullLiteral) {
{
Normal = 0,
Probing = 1,
- IgnoreAccessibility = 2
+ IgnoreAccessibility = 2,
+ IgnoreStaticUsing = 1 << 10
}
//
if (rc.HasSet (ResolveContext.Options.BaseInitializer))
flags |= ResolveContext.Options.BaseInitializer;
+
+ if (rc.HasSet (ResolveContext.Options.QueryClauseScope))
+ flags |= ResolveContext.Options.QueryClauseScope;
}
public ExceptionStatement CurrentTryBlock { get; set; }
NameOfScope = 1 << 17,
+ QueryClauseScope = 1 << 18,
+
///
/// Indicates the current context is in probing mode, no errors are reported.
///
variable.SetAssigned (DefiniteAssignment, generatedAssignment);
}
+ public void SetVariableAssigned (VariableInfo variable, DefiniteAssignmentBitSet da)
+ {
+ variable.SetAssigned (da, false);
+ }
+
public void SetStructFieldAssigned (VariableInfo variable, string name)
{
variable.SetStructFieldAssigned (DefiniteAssignment, name);
if (expr_type == target_type)
return true;
+ if (expr_type == InternalType.ThrowExpr)
+ return target_type.Kind != MemberKind.InternalCompilerType;
+
if (target_type.IsNullableType)
return ImplicitNulableConversion (null, expr, target_type) != null;
Expression e;
if (expr_type == target_type) {
- if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
+ if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod && expr_type != InternalType.ThrowExpr)
return expr;
return null;
}
return null;
}
+ if (expr_type == InternalType.ThrowExpr) {
+ return target_type.Kind == MemberKind.InternalCompilerType ? null : EmptyCast.Create (expr, target_type);
+ }
+
if (target_type.IsNullableType)
return ImplicitNulableConversion (ec, expr, target_type);
%token STRUCT
%token SWITCH
%token THIS
-%token THROW
+%token THROW
%token TRUE
%token TRY
%token TYPEOF
%token WHEN
%token INTERPOLATED_STRING
%token INTERPOLATED_STRING_END
+%token THROW_EXPR
/* C# keywords which are not really keywords */
%token GET
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod);
lbag.AddLocation ($$, GetLocation($2));
}
+ | identifier_inside_body COLON OUT named_argument_expr_or_out_variable_declaration
+ {
+ if (lang_version <= LanguageVersion.V_3)
+ FeatureIsNotAvailable (GetLocation ($1), "named argument");
+
+ var lt = (LocatedToken) $1;
+ $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, Argument.AType.Out);
+ lbag.AddLocation ($$, GetLocation($2));
+ }
+
;
named_argument_expr
: expression_or_error
-// | declaration_expression
+ ;
+
+named_argument_expr_or_out_variable_declaration
+ : expression_or_error
+ | out_variable_declaration
;
opt_named_modifier
{
$$ = Argument.AType.Ref;
}
- | OUT
- {
- $$ = Argument.AType.Out;
- }
;
opt_class_member_declarations
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null);
lbag.AddLocation ($$, GetLocation ($1));
}
- | COMMA IDENTIFIER ASSIGN
- {
- ++lexer.parsing_block;
- }
- event_variable_initializer
+ | COMMA IDENTIFIER ASSIGN event_variable_initializer
{
- --lexer.parsing_block;
var lt = (LocatedToken) $2;
- $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5);
+ $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $4);
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3));
}
;
if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) {
report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer",
current_event_field.GetSignatureForError ());
- }
+ }
+
+ ++lexer.parsing_block;
+ current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters;
+ start_block (lexer.Location);
}
variable_initializer
{
$$ = $2;
+
+ --lexer.parsing_block;
+ end_block (lexer.Location);
+ current_local_parameters = null;
}
;
$$ = new Argument ((Expression) $2, Argument.AType.Ref);
lbag.AddLocation ($$, GetLocation ($1));
}
- | REF declaration_expression
- {
- $$ = new Argument ((Expression) $2, Argument.AType.Ref);
- }
| OUT variable_reference
{
$$ = new Argument ((Expression) $2, Argument.AType.Out);
lbag.AddLocation ($$, GetLocation ($1));
}
- | OUT declaration_expression
+ | OUT out_variable_declaration
{
$$ = new Argument ((Expression) $2, Argument.AType.Out);
}
}
;
-declaration_expression
- : OPEN_PARENS declaration_expression CLOSE_PARENS
- {
- $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3));
- }
-/*
- | CHECKED open_parens_any declaration_expression CLOSE_PARENS
- {
- $$ = new CheckedExpr ((Expression) $3, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
- }
- | UNCHECKED open_parens_any declaration_expression CLOSE_PARENS
- {
- $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
- }
-*/
- | variable_type identifier_inside_body
+out_variable_declaration
+ : variable_type identifier_inside_body
{
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($1), "declaration expression");
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "out variable declaration");
var lt = (LocatedToken) $2;
var lv = new LocalVariable (current_block, lt.Value, lt.Location);
current_block.AddLocalName (lv);
$$ = new DeclarationExpression ((FullNamedExpression) $1, lv);
}
- | variable_type identifier_inside_body ASSIGN expression
- {
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($1), "declaration expression");
-
- var lt = (LocatedToken) $2;
- var lv = new LocalVariable (current_block, lt.Value, lt.Location);
- current_block.AddLocalName (lv);
- $$ = new DeclarationExpression ((FullNamedExpression) $1, lv) {
- Initializer = (Expression) $4
- };
- }
;
variable_reference
$$ = new Await ((Expression) $2, GetLocation ($1));
}
+ | THROW_EXPR prefixed_unary_expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (lexer.Location, "throw expression");
+
+ $$ = new ThrowExpression ((Expression) $2, GetLocation ($1));
+ }
| BANG error
{
Error_SyntaxError (yyToken);
{
var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2));
if ($4 != null) {
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($4), "type pattern matching");
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($4), "pattern matching");
var lt = (LocatedToken) $4;
- is_expr.Variable = new LocalVariable (current_block, lt.Value, lt.Location);
- current_block.AddLocalName (is_expr.Variable);
+ var lv = new LocalVariable (current_block, lt.Value, lt.Location);
+ is_expr.Variable = lv;
+ current_block.AddLocalName (lv);
}
$$ = is_expr;
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2));
lbag.AddLocation ($$, GetLocation ($4));
}
+ | null_coalescing_expression INTERR expression COLON THROW prefixed_unary_expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (lexer.Location, "throw expression");
+
+ var expr = new ThrowExpression ((Expression) $6, GetLocation ($5));
+ $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, expr, GetLocation ($2));
+ lbag.AddLocation ($$, GetLocation ($4));
+ }
| null_coalescing_expression INTERR expression error
{
Error_SyntaxError (yyToken);
;
throw_statement
- : THROW opt_expression SEMICOLON
+ : THROW expression SEMICOLON
{
$$ = new Throw ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3));
}
+ | THROW SEMICOLON
+ {
+ $$ = new Throw (null, GetLocation ($1));
+ lbag.AddStatement ($$, GetLocation ($2));
+ }
| THROW expression error
{
Error_SyntaxError (yyToken);
}
}
-Block
-end_block (Location loc)
+Block end_block (Location loc)
{
Block retval = current_block.Explicit;
retval.SetEndLocation (loc);
case Token.THIS:
return "this";
case Token.THROW:
+ case Token.THROW_EXPR:
return "throw";
case Token.TRUE:
return "true";
if (parsing_block == 0)
res = -1;
+ break;
+ case Token.THROW:
+ switch (current_token) {
+ case Token.ARROW:
+ case Token.OP_COALESCING:
+ case Token.INTERR:
+ res = Token.THROW_EXPR;
+ break;
+ }
+
break;
}
}
if (d == '.') {
- return Token.INTERR_OPERATOR;
+ d = reader.Peek ();
+ return d >= '0' && d <= '9' ? Token.INTERR : Token.INTERR_OPERATOR;
}
if (d != ' ') {
case Token.THIS:
case Token.NEW:
case Token.INTERPOLATED_STRING:
+ case Token.THROW:
next_token = Token.INTERR;
break;
foreach (var arg in arguments) {
if (arg.Type == InternalType.VarOutType) {
// Should be special error message about dynamic dispatch
- rc.Report.Error (8047, arg.Expr.Location, "Declaration expression cannot be used in this context");
+ rc.Report.Error (8197, arg.Expr.Location, "Cannot infer the type of implicitly-typed out variable `{0}'", ((DeclarationExpression) arg.Expr).Variable.Name);
}
}
return null;
}
+ protected void CheckExpressionVariable (ResolveContext rc)
+ {
+ if (rc.HasAny (ResolveContext.Options.BaseInitializer | ResolveContext.Options.FieldInitializerScope)) {
+ rc.Report.Error (8200, loc, "Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers");
+ } else if (rc.HasSet (ResolveContext.Options.QueryClauseScope)) {
+ rc.Report.Error (8201, loc, "Out variable and pattern variable declarations are not allowed within a query clause");
+ }
+ }
+
public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
{
rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
ec.Emit (OpCodes.Pop);
}
+ public virtual void EmitPrepare (EmitContext ec)
+ {
+ }
+
//
// Emits the expression into temporary field variable. The method
// should be used for await expressions only
{
}
+ public virtual Reachability MarkReachable (Reachability rc)
+ {
+ return rc;
+ }
+
//
// Special version of flow analysis for expressions which can return different
// on-true and on-false result. Used by &&, ||, ?: expressions
/// </summary>
public abstract class ExpressionStatement : Expression
{
- public virtual void MarkReachable (Reachability rc)
- {
- }
-
public virtual ExpressionStatement ResolveStatement (BlockContext ec)
{
Expression e = Resolve (ec);
#endif
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return child.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
// Nothing to clone
{
return orig_expr.MakeExpression (ctx);
}
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return expr.MarkReachable (rc);
+ }
}
//
return null;
}
- public bool IsPossibleTypeOrNamespace (IMemberContext mc)
+ bool IsPossibleTypeOrNamespace (IMemberContext mc)
{
- return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null;
+ //
+ // Has to ignore static usings because we are looking for any member not just type
+ // in this context
+ //
+ return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing | LookupMode.IgnoreStaticUsing, loc) != null;
}
public bool IsPossibleType (IMemberContext mc)
return me;
}
+ //
+ // Stage 3: Lookup nested types, namespaces and type parameters in the context
+ //
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
+ if (IsPossibleTypeOrNamespace (rc)) {
+ return ResolveAsTypeOrNamespace (rc, false);
+ }
+ }
+
var expr = NamespaceContainer.LookupStaticUsings (rc, Name, Arity, loc);
if (expr != null) {
if (Arity > 0) {
return expr;
}
- //
- // Stage 3: Lookup nested types, namespaces and type parameters in the context
- //
- if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
- if (IsPossibleTypeOrNamespace (rc)) {
- return ResolveAsTypeOrNamespace (rc, false);
- }
- }
-
if ((restrictions & MemberLookupRestrictions.NameOfExcluded) == 0 && Name == "nameof")
return new NameOf (this);
expr.EmitSideEffect (ec);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ expr.EmitPrepare (ec);
+ }
+
public override void FlowAnalysis (FlowAnalysisContext fc)
{
expr.FlowAnalysis (fc);
public override Expression CreateExpressionTree (ResolveContext ec)
{
if (Variable != null)
- throw new NotSupportedException ();
+ ec.Report.Error (8122, loc, "An expression tree cannot contain a pattern matching operator");
Arguments args = Arguments.CreateForExpressionTree (ec, null,
expr.CreateExpressionTree (ec),
ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ base.EmitPrepare (ec);
+
+ if (Variable != null)
+ Variable.CreateBuilder (ec);
+ }
+
void EmitPatternMatch (EmitContext ec)
{
var no_match = ec.DefineLabel ();
value_on_stack = false;
}
- Variable.CreateBuilder (ec);
+ //
+ // It's ok to have variable builder create out of order. It simplified emit
+ // of statements like while (condition) { }
+ //
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
+
Variable.EmitAssign (ec);
if (expr_unwrap != null) {
fc.SetVariableAssigned (Variable.VariableInfo, true);
}
+ public override void FlowAnalysisConditional (FlowAnalysisContext fc)
+ {
+ if (Variable == null) {
+ base.FlowAnalysisConditional (fc);
+ return;
+ }
+
+ expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignmentOnTrue = fc.BranchDefiniteAssignment ();
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ fc.SetVariableAssigned (Variable.VariableInfo, fc.DefiniteAssignmentOnTrue);
+ }
+
protected override void ResolveProbeType (ResolveContext rc)
{
if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) {
Expression ResolveResultExpression (ResolveContext ec)
{
+ if (Variable != null) {
+ if (expr is NullLiteral) {
+ ec.Report.Error (8117, loc, "Cannot use null as pattern matching operand");
+ return this;
+ }
+
+ CheckExpressionVariable (ec);
+ }
+
TypeSpec d = expr.Type;
bool d_is_nullable = false;
// If E is a method group or the null literal, or if the type of E is a reference
// type or a nullable type and the value of E is null, the result is false
//
- if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+ if (expr.IsNull)
return CreateConstantResult (ec, false);
if (d.IsNullableType) {
TypeSpec t = probe_type_expr;
bool t_is_nullable = false;
if (t.IsNullableType) {
+ if (Variable != null) {
+ ec.Report.Error (8116, loc, "The nullable type `{0}' pattern matching is not allowed. Consider using underlying type `{1}'",
+ t.GetSignatureForError (), Nullable.NullableInfo.GetUnderlyingType (t).GetSignatureForError ());
+ }
+
var ut = Nullable.NullableInfo.GetUnderlyingType (t);
if (!ut.IsGenericParameter) {
t = ut;
return ResolveGenericParameter (ec, d, tps);
if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- ec.Report.Warning (1981, 3, loc,
- "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
- OperatorName, t.GetSignatureForError ());
+ if (Variable != null) {
+ ec.Report.Error (8208, loc, "The type `{0}' pattern matching is not allowed", t.GetSignatureForError ());
+ } else {
+ ec.Report.Warning (1981, 3, loc,
+ "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
+ OperatorName, t.GetSignatureForError ());
+ }
}
if (TypeManager.IsGenericParameter (d))
public override Expression CreateExpressionTree (ResolveContext rc)
{
- rc.Report.Error (8046, loc, "An expression tree cannot contain a declaration expression");
+ rc.Report.Error (8198, loc, "An expression tree cannot contain out variable declaration");
return null;
}
bool DoResolveCommon (ResolveContext rc)
{
+ CheckExpressionVariable (rc);
+
var var_expr = VariableType as VarExpr;
if (var_expr != null) {
type = InternalType.VarOutType;
return value;
}
}
+
+ class ThrowExpression : ExpressionStatement
+ {
+ Expression expr;
+
+ public ThrowExpression (Expression expr, Location loc)
+ {
+ this.expr = expr;
+ this.loc = loc;
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ var target = (ThrowExpression)t;
+ target.expr = expr.Clone (clonectx);
+ }
+
+ public override bool ContainsEmitWithAwait ()
+ {
+ return expr.ContainsEmitWithAwait ();
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8188, loc, "An expression tree cannot not contain a throw expression");
+ return expr;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ expr = expr.Resolve (rc, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+
+ if (expr == null)
+ return null;
+
+ expr = Throw.ConvertType (rc, expr);
+
+ eclass = ExprClass.Value;
+ type = InternalType.ThrowExpr;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ EmitStatement (ec);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ expr.Emit (ec);
+
+ ec.Emit (OpCodes.Throw);
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return Reachability.CreateUnreachable ();
+ }
+ }
}
// Some types cannot be used as type arguments
//
if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
- bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType)
+ bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType ||
+ bound.Type == InternalType.ThrowExpr)
return;
var a = bounds [index];
{
}
- protected override MethodGroupExpr DoResolveOverload (ResolveContext ec)
+ protected override MethodGroupExpr DoResolveOverload (ResolveContext rc)
{
- MethodGroupExpr rmg = mg.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.None);
- return rmg;
+ using (rc.Set (ResolveContext.Options.QueryClauseScope)) {
+ return mg.OverloadResolve (rc, ref arguments, this, OverloadResolver.Restrictions.None);
+ }
}
protected override Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
match = texpr_fne;
}
- if (types_using_table != null) {
+ if (types_using_table != null && (mode & LookupMode.IgnoreStaticUsing) == 0) {
foreach (var using_type in types_using_table) {
var type = MemberCache.FindNestedType (using_type, name, arity, true);
if (type == null)
type = ltype;
return this;
}
+ } else if (ltype == InternalType.ThrowExpr) {
+ //
+ // LAMESPEC: I am not really sure what's point of allowing throw on left side
+ //
+ return ReducedExpression.Create (right, this, false).Resolve (ec);
} else {
return null;
}
case LanguageVersion.V_6:
version = "6.0";
break;
+ case LanguageVersion.V_7:
+ version = "7.0";
+ break;
default:
throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
}
V_4 = 4,
V_5 = 5,
V_6 = 6,
+ V_7 = 7,
Experimental = 100,
- Default = LanguageVersion.V_6,
+ Default = V_7,
}
public enum RuntimeVersion
case "6":
settings.Version = LanguageVersion.V_6;
return ParseResult.Success;
+ case "7":
+ settings.Version = LanguageVersion.V_7;
+ return ParseResult.Success;
case "experimental":
settings.Version = LanguageVersion.Experimental;
return ParseResult.Success;
- case "future":
- report.Warning (8000, 1, "Language version `future' is no longer supported");
- goto case "6";
}
- report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 6", value);
+ report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 7", value);
return ParseResult.Error;
case "/codepage":
ec.Emit (OpCodes.Br, ec.LoopBegin);
ec.MarkLabel (while_loop);
+ expr.EmitPrepare (ec);
+
Statement.Emit (ec);
ec.MarkLabel (ec.LoopBegin);
public class Return : ExitStatement
{
Expression expr;
+ bool expr_returns;
public Return (Expression expr, Location l)
{
if (expr != null)
expr.FlowAnalysis (fc);
- base.DoFlowAnalysis (fc);
+ if (!expr_returns)
+ base.DoFlowAnalysis (fc);
+
return true;
}
public override Reachability MarkReachable (Reachability rc)
{
base.MarkReachable (rc);
+
+ if (Expr != null) {
+ rc = Expr.MarkReachable (rc);
+ expr_returns = rc.IsUnreachable;
+ }
+
return Reachability.CreateUnreachable ();
}
}
}
+ public static Expression ConvertType (ResolveContext rc, Expression expr)
+ {
+ var et = rc.BuiltinTypes.Exception;
+ if (Convert.ImplicitConversionExists (rc, expr, et))
+ expr = Convert.ImplicitConversion (rc, expr, et, expr.Location);
+ else {
+ rc.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
+ expr = EmptyCast.Create (expr, et);
+ }
+
+ return expr;
+ }
+
public override bool Resolve (BlockContext ec)
{
if (expr == null) {
if (expr == null)
return false;
- var et = ec.BuiltinTypes.Exception;
- if (Convert.ImplicitConversionExists (ec, expr, et))
- expr = Convert.ImplicitConversion (ec, expr, et, loc);
- else
- ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
+ expr = ConvertType (ec, expr);
return true;
}
public override Reachability MarkReachable (Reachability rc)
{
- var init = initializer as ExpressionStatement;
- if (init != null)
- init.MarkReachable (rc);
-
- return base.MarkReachable (rc);
+ base.MarkReachable (rc);
+ return initializer == null ? rc : initializer.MarkReachable (rc);
}
protected override void CloneTo (CloneContext clonectx, Statement target)
}
}
+ public bool Created {
+ get {
+ return builder != null;
+ }
+ }
+
public bool IsDeclared {
get {
return type != null;
public static readonly InternalType Namespace = new InternalType ("<namespace>");
public static readonly InternalType ErrorType = new InternalType ("<error>");
public static readonly InternalType VarOutType = new InternalType ("var out");
+ public static readonly InternalType ThrowExpr = new InternalType ("throw expression");
readonly string name;
var t = (Int32)sbyte.MaxValue;
}
+ void Test_22 (bool args)
+ {
+ var x = args ?.2f : -.2f;
+ }
+
static void Helper<T> (T arg)
{
}
# csXXXX.cs IGNORE : adds test to ignore list
gtest-230.cs
+test-pattern-02.cs
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+
+ }
+
+ int ImportScope (int scope)
+ {
+ switch (scope) {
+ case 200:
+ throw new NotImplementedException ();
+ }
+
+ throw new NotSupportedException ();
+ }
+}
\ No newline at end of file
return 3;
if (Test.A == Test.B)
return 4;
+
+ const A e2 = 3 - A.b;
+ if (e2 != A.a)
+ return 5;
return 0;
}
-// Compiler options: -langversion:experimental
using System;
class DeclarationExpression
return 2;
}
- Out (out int o2 = 2);
- if (o2 != 3)
- return 3;
-
Out (out var o3);
if (o3 != 3)
return 4;
- Ref (ref int r = 2);
- if (r != 7)
- return 5;
-
- Ref (ref ((var r2 = 3)));
- if (r2 != 8)
- return 6;
-
-// Out2 (str: "b", v: out var o5);
-// if (o5 != 9)
-// return 7;
-
- Out3 (out var o6 = 9m);
- if (o6.GetType () != typeof (decimal))
- return 8;
+ Out2 (str: "b", v: out var o5);
+ if (o5 != 9)
+ return 7;
Console.WriteLine ("ok");
return 0;
v = 9;
return true;
}
-
- static void Out3<T> (out T t)
- {
- t = default (T);
- }
-
- static void Ref (ref int arg)
- {
- arg += 5;
- }
}
\ No newline at end of file
-// Compiler options: -langversion:experimental
+using System;
-using static System.Console;
-
-public class DeclarationExpressions
+public class C
{
- public static void Main()
- {
- // TODO:
- //Test (int value = 5);
- //WriteLine (value);
- }
-
- void M2 ()
+ public static void Main ()
{
-// for (int i = 0; int v = 2; ++i) {
-
-// }
-
}
- static int Test (int x)
- {
- WriteLine (x);
- return x;
- }
+ bool Test1 => int.TryParse ("1", out int x);
+ int Test2 => int.TryParse ("2", out int x) ? x : 0;
}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Linq;
+
+public class C
+{
+ public static void Main ()
+ {
+ var a = "abcdef";
+
+ var t1 = from x in Foo (a, out var q1) select x;
+ var t2 = from x in a join y in Foo (a, out var q2) on x equals y select x;
+ }
+
+ public static T Foo<T> (T x, out T z) => z = x;
+}
\ No newline at end of file
--- /dev/null
+public class C
+{
+ public static void Main ()
+ {
+ Test2 (Test (out var x1), x1);
+ }
+
+ static int Test (out int x)
+ {
+ x = 1;
+ return 2;
+ }
+
+ static int Test2 (int x, int y)
+ {
+ return 2;
+ }
+}
\ No newline at end of file
-// Compiler options: -langversion:experimental
-
using System;
class TypePattern
{
object o = 3;
bool r = o is System.String t1;
- if (t1 != null)
- return 1;
-
if (r)
return 2;
if (o is string t2)
return 3;
- if (t2 != null)
- return 4;
-
- object o2 = (int?) 4;
- bool r2 = o2 is byte? t3;
-
- if (t3 != null)
- return 5;
-
- if (r2)
- return 6;
-
long? l = 5;
bool r3 = l is long t4;
- if (t4 != 5)
- return 7;
if (!r3)
return 8;
Console.WriteLine ("ok");
return 0;
}
+
+ static void Test1 (object arg)
+ {
+ while (arg is int b) {
+ b = 2;
+ }
+ }
+
+ static string Test2 (object arg)
+ {
+ if (arg is string s) {
+ return s;
+ } else {
+ s = "";
+ }
+
+ return s;
+ }
}
\ No newline at end of file
object o4 = (byte?)255;
var ggg = o4 is 255;
- if (!ggg)
+ if (ggg)
return 8;
if (o4 is null)
return 9;
object o5 = (double)-255;
- if (!(o5 is -byte.MaxValue))
+ if (o5 is -byte.MaxValue)
return 10;
object o6 = MyEnum.V_4;
--- /dev/null
+using System;
+using static TestClass;
+
+internal class Program
+{
+ public static void Main (string[] args)
+ {
+ var res = Directions.Up;
+ }
+}
+
+public enum Directions
+{
+ Up,
+ NotUp,
+}
+
+public static class TestClass
+{
+ public static int Directions;
+}
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ Func<object> f = () => throw null;
+ }
+
+ public int Test () => throw null;
+
+ object Foo ()
+ {
+ return null;
+ }
+
+ public object Test2 () => Foo () ?? throw null;
+
+ static void Test3 (out int z) => throw null;
+
+ int this [int x] {
+ get => throw null;
+ }
+
+ public event Action Event {
+ add => throw null;
+ remove => throw null;
+ }
+
+ void TestExpr_1 (bool b)
+ {
+ int x = b ? throw new NullReferenceException () : 1;
+ }
+
+ void TestExpr_2 (bool b)
+ {
+ int x = b ? 2 : throw new NullReferenceException ();
+ }
+
+ void TestExpr_3 (string s)
+ {
+ s = s ?? throw new NullReferenceException ();
+ }
+
+ void TestExpr_4 ()
+ {
+ throw new ApplicationException () ?? throw new NullReferenceException() ?? throw null;
+ }
+
+ void TestExpr_5 ()
+ {
+ Action a = () => throw new ApplicationException () ?? throw new NullReferenceException() ?? throw null;
+ }
+
+ static int TestExpr_6 (out int z) => throw null;
+
+ int TestExpr_7 (out int z)
+ {
+ return true ? throw new NullReferenceException () : 1;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+class Program
+{
+ public static int Main ()
+ {
+ Console.WriteLine (M (1));
+ try {
+ Console.WriteLine (M (null));
+ } catch (Exception) {
+ Console.WriteLine ("thrown");
+ return 0;
+ }
+
+ return 1;
+ }
+
+ static string M (object data)
+ {
+ return data?.ToString () ?? throw null;
+ }
+}
\ No newline at end of file
<method name="Void Test_21()" attrs="129">
<size>5</size>
</method>
+ <method name="Void Test_22(Boolean)" attrs="129">
+ <size>24</size>
+ </method>
</type>
</test>
<test name="gtest-410.cs">
</method>
</type>
</test>
+ <test name="test-946.cs">
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Int32 ImportScope(Int32)" attrs="129">
+ <size>29</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-95.cs">
<type name="X">
<method name="Int32 Main()" attrs="150">
<test name="test-decl-expr-01.cs">
<type name="DeclarationExpression">
<method name="Int32 Main()" attrs="150">
- <size>223</size>
+ <size>121</size>
</method>
<method name="Boolean Out(Int32 ByRef)" attrs="145">
<size>13</size>
<method name="Boolean Out2(Int32 ByRef, System.String)" attrs="145">
<size>14</size>
</method>
- <method name="Void Out3[T](T ByRef)" attrs="145">
- <size>17</size>
- </method>
- <method name="Void Ref(Int32 ByRef)" attrs="145">
- <size>8</size>
- </method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
</test>
<test name="test-decl-expr-02.cs">
- <type name="DeclarationExpressions">
+ <type name="C">
<method name="Void Main()" attrs="150">
<size>2</size>
</method>
- <method name="Void M2()" attrs="129">
- <size>2</size>
+ <method name="Boolean get_Test1()" attrs="2177">
+ <size>20</size>
</method>
- <method name="Int32 Test(Int32)" attrs="145">
+ <method name="Int32 get_Test2()" attrs="2177">
+ <size>32</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-decl-expr-03.cs">
+ <type name="C">
+ <method name="Void Main()" attrs="150">
+ <size>153</size>
+ </method>
+ <method name="T Foo[T](T, T ByRef)" attrs="150">
+ <size>18</size>
+ </method>
+ <method name="Char <Main>m__0(Char)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Char <Main>m__1(Char)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Char <Main>m__2(Char)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Char <Main>m__3(Char, Char)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-decl-expr-04.cs">
+ <type name="C">
+ <method name="Void Main()" attrs="150">
<size>16</size>
</method>
+ <method name="Int32 Test(Int32 ByRef)" attrs="145">
+ <size>13</size>
+ </method>
+ <method name="Int32 Test2(Int32, Int32)" attrs="145">
+ <size>10</size>
+ </method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
<test name="test-pattern-01.cs">
<type name="TypePattern">
<method name="Int32 Main()" attrs="150">
- <size>227</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- </test>
- <test name="test-pattern-02.cs">
- <type name="ConstantPattern">
- <method name="Int32 Main()" attrs="150">
- <size>609</size>
+ <size>118</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
- </type>
- <type name="<PatternMatchingHelper>">
- <method name="Boolean NumberMatcher(System.Object, System.Object, Boolean)" attrs="150">
- <size>69</size>
+ <method name="Void Test1(System.Object)" attrs="145">
+ <size>24</size>
</method>
- </type>
- <type name="ConstantPattern">
- <method name="Boolean Generic[T](T)" attrs="145">
- <size>28</size>
+ <method name="System.String Test2(System.Object)" attrs="145">
+ <size>39</size>
</method>
</type>
</test>
</method>
</type>
</test>
+ <test name="test-static-using-13.cs">
+ <type name="Program">
+ <method name="Void Main(System.String[])" attrs="150">
+ <size>4</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-throw-expr-01.cs">
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>32</size>
+ </method>
+ <method name="Int32 Test()" attrs="134">
+ <size>10</size>
+ </method>
+ <method name="System.Object Foo()" attrs="129">
+ <size>10</size>
+ </method>
+ <method name="System.Object Test2()" attrs="134">
+ <size>23</size>
+ </method>
+ <method name="Void Test3(Int32 ByRef)" attrs="145">
+ <size>3</size>
+ </method>
+ <method name="Int32 get_Item(Int32)" attrs="2177">
+ <size>10</size>
+ </method>
+ <method name="Void add_Event(System.Action)" attrs="2182">
+ <size>3</size>
+ </method>
+ <method name="Void remove_Event(System.Action)" attrs="2182">
+ <size>3</size>
+ </method>
+ <method name="Void TestExpr_1(Boolean)" attrs="129">
+ <size>21</size>
+ </method>
+ <method name="Void TestExpr_2(Boolean)" attrs="129">
+ <size>21</size>
+ </method>
+ <method name="Void TestExpr_3(System.String)" attrs="129">
+ <size>18</size>
+ </method>
+ <method name="Void TestExpr_4()" attrs="129">
+ <size>16</size>
+ </method>
+ <method name="Void TestExpr_5()" attrs="129">
+ <size>32</size>
+ </method>
+ <method name="System.Object <Main>m__0()" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Void <TestExpr_5>m__1()" attrs="145">
+ <size>3</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ <method name="Int32 TestExpr_6(Int32 ByRef)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Int32 TestExpr_7(Int32 ByRef)" attrs="129">
+ <size>15</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-throw-expr-02.cs">
+ <type name="Program">
+ <method name="Int32 Main()" attrs="150">
+ <size>63</size>
+ </method>
+ <method name="System.String M(System.Object)" attrs="145">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-var-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
<SchemaVersion>2.0</SchemaVersion>\r
<ProjectGuid>{FA920637-C202-4E75-AC0F-1A8DBD631DF1}</ProjectGuid>\r
<OutputType>Exe</OutputType>\r
- <NoWarn>1699</NoWarn>\r
+ <NoWarn>1699,1699</NoWarn>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Windows_NT'">win32</HostPlatform>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix' and $([System.IO.File]::Exists('/usr/lib/libc.dylib'))">darwin</HostPlatform>\r
<HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix'">linux</HostPlatform>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
<DebugSymbols>true</DebugSymbols>\r
<DebugType>full</DebugType>\r
- <NoWarn>1699</NoWarn>\r
+ <NoWarn>1699,1699</NoWarn>\r
<Optimize>false</Optimize>\r
- <DefineConstants>TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
+ <DefineConstants>TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS;NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
<WarningLevel>4</WarningLevel>\r
</PropertyGroup>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
<DebugType>pdbonly</DebugType>\r
- <NoWarn>1699</NoWarn>\r
+ <NoWarn>1699,1699</NoWarn>\r
<Optimize>true</Optimize>\r
- <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
+ <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS;NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM;MULTIPLEX_OS</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
<WarningLevel>4</WarningLevel>\r
</PropertyGroup>\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\LoadException.cs" />\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\MarkException.cs" />\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\MethodAction.cs" />\r
+ <Compile Include="..\..\..\external\linker\linker\Mono.Linker\MethodReferenceExtensions.cs" />\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\Pipeline.cs" />\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\TypePreserve.cs" />\r
+ <Compile Include="..\..\..\external\linker\linker\Mono.Linker\TypeReferenceExtensions.cs" />\r
<Compile Include="..\..\..\external\linker\linker\Mono.Linker\XApiReader.cs" />\r </ItemGroup>\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
Other similar extension points exist, see Microsoft.Common.targets.\r
<ItemGroup>\r
<Folder Include="Properties\" />\r
</ItemGroup>\r
- <ItemGroup>\r
- <EmbeddedResource Include="Descriptors/mscorlib.xml">\r
- <LogicalName>mscorlib.xml</LogicalName>\r
- </EmbeddedResource>\r
- <EmbeddedResource Include="Descriptors/System.xml">\r
- <LogicalName>System.xml</LogicalName>\r
- </EmbeddedResource>\r
- <EmbeddedResource Include="Descriptors/System.Core.xml">\r
- <LogicalName>System.Core.xml</LogicalName>\r
- </EmbeddedResource>\r
- <EmbeddedResource Include="Descriptors/System.Drawing.xml">\r
- <LogicalName>System.Drawing.xml</LogicalName>\r
- </EmbeddedResource>\r
- <EmbeddedResource Include="Descriptors/System.Web.xml">\r
- <LogicalName>System.Web.xml</LogicalName>\r
- </EmbeddedResource>\r
- <EmbeddedResource Include="Descriptors/Mono.Posix.xml">\r
- <LogicalName>Mono.Posix.xml</LogicalName>\r
- </EmbeddedResource>\r
- </ItemGroup>\r
</Project>\r
static readonly Universe universe = new Universe ();
static readonly Dictionary<string, string> loaded_assemblies = new Dictionary<string, string> ();
- static readonly string resourcePathSeparator = (Path.DirectorySeparatorChar == '\\') ? $"\\{Path.DirectorySeparatorChar}" : $"{Path.DirectorySeparatorChar}";
public static string GetAssemblyName (string path)
{
+ string resourcePathSeparator = style == "windows" ? "\\\\" : "/";
string name = Path.GetFileName (path);
// A bit of a hack to support satellite assemblies. They all share the same name but
ret = mono->read_func (mono->instance, out, outl, &wantMore);
- if (ret < 0)
+ if (ret < 0) {
+ errno = EIO;
return -1;
+ }
if (ret > 0)
return ret;
;
}
+MONO_API int
+mono_btls_ssl_shutdown (MonoBtlsSsl *ptr)
+{
+ return SSL_shutdown (ptr->ssl);
+}
+
+MONO_API void
+mono_btls_ssl_set_quiet_shutdown (MonoBtlsSsl *ptr, int mode)
+{
+ SSL_set_quiet_shutdown (ptr->ssl, mode);
+}
+
MONO_API void
mono_btls_ssl_set_bio (MonoBtlsSsl *ptr, BIO *bio)
{
void
mono_btls_ssl_close (MonoBtlsSsl *ptr);
+int
+mono_btls_ssl_shutdown (MonoBtlsSsl *ptr);
+
+MONO_API void
+mono_btls_ssl_set_quiet_shutdown (MonoBtlsSsl *ptr, int mode);
+
int
mono_btls_ssl_get_error (MonoBtlsSsl *ptr, int ret_code);
#include "mono/metadata/class-internals.h"
#include "mono/utils/mono-compiler.h"
-#if defined(__native_client__) && defined(__GLIBC__)
-volatile int __nacl_thread_suspension_needed = 0;
-void __nacl_suspend_thread_if_needed() {}
-#endif
-
void
dump_table_assembly (MonoImage *m)
{
extern gboolean substitute_with_mscorlib_p;
+static char *
+get_token_comment (const char *prefix, guint32 token);
+
static MonoGenericContainer *
get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container);
/* Check if this is a nested type */
token = MONO_TOKEN_TYPE_DEF | (idx);
token = mono_metadata_nested_in_typedef (m, token);
- tstring = show_tokens ? g_strdup_printf ("/*%08x*/", token) : NULL;
+ tstring = get_token_comment (NULL, token);
if (token) {
char *outer;
if (show_tokens) {
int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
- result = g_strdup_printf ("%s/*%08x*/", res->str, token);
- } else
+ result = get_token_comment (res->str, token);
+ g_string_free (res, TRUE);
+ } else {
result = res->str;
-
- g_string_free (res, FALSE);
+ g_string_free (res, FALSE);
+ }
return result;
}
if (show_tokens) {
int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
- char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
+ char *temp = get_token_comment (ret, token);
g_free (ret);
ret = temp;
}
}
if (show_tokens) {
- *result = g_strdup_printf ("%s/*%08x*/", temp, token);
+ *result = get_token_comment (temp, token);
g_free (temp);
} else
*result = temp;
return full_sig;
}
+/**
+ * get_token_comment:
+ *
+ * If show_tokens is TRUE, return "prefix""token(table)".
+ * If show_tokens is FALSE, return "prefix" or NULL if prefix is NULL.
+ * Caller is responsible for freeing.
+ */
+char *
+get_token_comment (const char *prefix, guint32 token)
+{
+ if (!show_tokens)
+ return prefix ? g_strdup_printf ("%s", prefix) : NULL;
+ gint32 tableidx = mono_metadata_token_table (token);
+ if ((tableidx < 0) || (tableidx > MONO_TABLE_LAST))
+ return g_strdup_printf ("%s/*%08x*/", prefix ? prefix : "", token);
+ else
+ return g_strdup_printf ("%s/*%08x(%s)*/", prefix ? prefix : "", token, mono_meta_table_name (tableidx));
+}
+
/**
* get_field:
* @m: metadata context
{
int idx = mono_metadata_token_index (token);
guint32 cols [MONO_FIELD_SIZE];
- char *sig, *res, *type, *estype, *esname;
+ char *sig, *res, *type, *estype, *esname, *token_comment;
guint32 type_idx;
/*
type = get_typedef (m, type_idx);
estype = get_escaped_name (type);
esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
- res = g_strdup_printf ("%s %s%s%s",
+ token_comment = get_token_comment (NULL, token);
+ res = g_strdup_printf ("%s %s%s%s%s",
sig,
estype ? estype : "",
estype ? "::" : "",
- esname);
+ esname,
+ token_comment ? token_comment : ""
+ );
g_free (type);
g_free (sig);
g_free (estype);
g_free (esname);
+ g_free (token_comment);
return res;
}
container = mono_method_get_generic_container (((MonoMethodInflated *) mh)->declaring);
esname = get_escaped_name (mh->name);
sig = dis_stringify_type (m, &mh->klass->byval_arg, TRUE);
- if (show_tokens)
- name = g_strdup_printf ("%s/*%08x*/%s%s", sig ? sig : "", token, sig ? "::" : "", esname);
- else
- name = g_strdup_printf ("%s%s%s", sig ? sig : "", sig ? "::" : "", esname);
+ char *token_comment = get_token_comment (NULL, token);
+ name = g_strdup_printf ("%s%s%s%s", sig ? sig : "", token_comment ? token_comment : "", sig ? "::" : "", esname);
g_free (sig);
g_free (esname);
+ g_free (token_comment);
} else {
name = NULL;
mono_error_cleanup (&error);
}
if (show_tokens) {
- char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
+ char *retval = get_token_comment (sig, token);
g_free (sig);
return retval;
} else
static void
usage (void)
{
- GString *args = g_string_new ("[--output=filename] [--filter=filename] [--help] [--mscorlib]\n");
+ GString *args = g_string_new ("[--output=filename] [--filter=filename]\n");
int i;
+
+ g_string_append (args, "[--help] [--mscorlib] [--show-tokens] [--show-method-tokens]\n");
for (i = 0; table_list [i].name != NULL; i++){
g_string_append (args, "[");
.TP
.I "--show-method-tokens"
Display tokens for disassembled methods.
+.TP
+.I "--show-tokens"
+Display tokens for strings, types, methods, fields, etc.
.SH OPTIONS TO DISPLAY METADATA TABLES
The following options are used to display metadata tables instead of
disassembling the CIL image.
mono-route.c \
mono-route.h \
monitor.h \
- nacl-stub.c \
normalization-tables.h \
number-formatter.h \
number-ms.c \
if (g_hasenv ("MONO_NO_UNLOAD"))
return;
-#ifdef __native_client__
- return;
-#endif
-
MonoException *exc = NULL;
mono_domain_try_unload (domain, (MonoObject**)&exc);
if (exc)
static GList *loaded_assemblies = NULL;
static MonoAssembly *corlib;
-#if defined(__native_client__)
-
-/* On Native Client, allow mscorlib to be loaded from memory */
-/* instead of loaded off disk. If these are not set, default */
-/* mscorlib loading will take place */
-
-/* NOTE: If mscorlib data is passed to mono in this way then */
-/* it needs to remain allocated during the use of mono. */
-
-static void *corlibData = NULL;
-static size_t corlibSize = 0;
-
-void
-mono_set_corlib_data (void *data, size_t size)
-{
- corlibData = data;
- corlibSize = size;
-}
-
-#endif
-
static char* unquote (const char *str);
/* This protects loaded_assemblies and image->references */
}
}
-/* Native Client can't get this info from an environment variable so */
-/* it's passed in to the runtime, or set manually by embedding code. */
-#ifdef __native_client__
-char* nacl_mono_path = NULL;
-#endif
-
static void
check_path_env (void)
{
return;
char* path = g_getenv ("MONO_PATH");
-#ifdef __native_client__
- if (!path)
- path = strdup (nacl_mono_path);
-#endif
if (!path)
return;
return corlib;
}
- // In native client, Corlib is embedded in the executable as static variable corlibData
-#if defined(__native_client__)
- if (corlibData != NULL && corlibSize != 0) {
- int status = 0;
- /* First "FALSE" instructs mono not to make a copy. */
- /* Second "FALSE" says this is not just a ref. */
- MonoImage* image = mono_image_open_from_data_full (corlibData, corlibSize, FALSE, &status, FALSE);
- if (image == NULL || status != 0)
- g_print("mono_image_open_from_data_full failed: %d\n", status);
- corlib = mono_assembly_load_from_full (image, "mscorlib", &status, FALSE);
- if (corlib == NULL || status != 0)
- g_print ("mono_assembly_load_from_full failed: %d\n", status);
- if (corlib)
- return corlib;
- }
-#endif
-
// A nonstandard preload hook may provide a special mscorlib assembly
aname = mono_assembly_name_new ("mscorlib.dll");
corlib = invoke_assembly_preload_hook (aname, assemblies_path);
* we used to do this only when running on valgrind,
* but it happens also in other setups.
*/
-#if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && !defined(__native_client__)
+#if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK)
{
size_t size;
void *sstart;
GC_stackbottom = (char*)ss.ss_sp;
}
-#elif defined(__native_client__)
- /* Do nothing, GC_stackbottom is set correctly in libgc */
#else
{
int dummy;
* Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com)
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
-#if defined(__native_client__)
-#include "console-null.c"
-#else
-
#include <config.h>
#include <glib.h>
#include <stdio.h>
return TRUE;
}
-#endif /* #if defined(__native_client__) */
-
gboolean ret;
gint64 start;
-#if defined(__native_client__)
- return FALSE;
-#endif
-
if (mono_thread_internal_current () == gc_thread)
/* We are called from inside a finalizer, not much we can do here */
return FALSE;
return mono_array_addr_with_size (raw, size, idx);
}
+gunichar2*
+mono_string_handle_pin_chars (MonoStringHandle handle, uint32_t *gchandle)
+{
+ g_assert (gchandle != NULL);
+ *gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, handle), TRUE);
+ MonoString *raw = MONO_HANDLE_RAW (handle);
+ return mono_string_chars (raw);
+}
+
void
mono_array_handle_memcpy_refs (MonoArrayHandle dest, uintptr_t dest_idx, MonoArrayHandle src, uintptr_t src_idx, uintptr_t len)
{
#define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE))))
+/* Given an object and a MonoClassField, return the value (must be non-object)
+ * of the field. It's the caller's responsibility to check that the object is
+ * of the correct class. */
+#define MONO_HANDLE_GET_FIELD_VAL(HANDLE,TYPE,FIELD) *(TYPE *)(mono_handle_unsafe_field_addr (MONO_HANDLE_CAST (MonoObject, (HANDLE)), (FIELD)))
+
+#define MONO_HANDLE_NEW_GET_FIELD(HANDLE,TYPE,FIELD) MONO_HANDLE_NEW (TYPE, *(TYPE**)(mono_handle_unsafe_field_addr (MONO_HANDLE_CAST (MonoObject, (HANDLE)), (FIELD))))
+
+#define MONO_HANDLE_SET_FIELD_VAL(HANDLE,TYPE,FIELD,VAL) do { \
+ MonoObjectHandle __obj = (HANDLE); \
+ MonoClassField *__field = (FIELD); \
+ TYPE __value = (VAL); \
+ *(TYPE*)(mono_handle_unsafe_field_addr (__obj, __field)) = __value; \
+ } while (0)
/* Baked typed handles we all want */
TYPED_HANDLE_DECL (MonoString);
TYPED_HANDLE_DECL (MonoException);
TYPED_HANDLE_DECL (MonoAppContext);
+/* Unfortunately MonoThreadHandle is already a typedef used for something unrelated. So
+ * the coop handle for MonoThread* is MonoThreadObjectHandle.
+ */
+typedef MonoThread MonoThreadObject;
+TYPED_HANDLE_DECL (MonoThreadObject);
+
#define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE)
/*
mono_gc_wbarrier_generic_store (&dest->__raw, src ? MONO_HANDLE_RAW(src) : NULL);
}
+/* It is unsafe to call this function directly - it does not pin the handle! Use MONO_HANDLE_GET_FIELD_VAL(). */
+static inline gchar*
+mono_handle_unsafe_field_addr (MonoObjectHandle h, MonoClassField *field)
+{
+ return ((gchar *)MONO_HANDLE_RAW (h)) + field->offset;
+}
+
//FIXME this should go somewhere else
MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
#define MONO_ARRAY_HANDLE_PIN(handle,type,index,gchandle_out) mono_array_handle_pin_with_size (MONO_HANDLE_CAST(MonoArray,(handle)), sizeof (type), (index), (gchandle_out))
+gunichar2 *
+mono_string_handle_pin_chars (MonoStringHandle s, uint32_t *gchandle_out);
+
void
mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
void
mono_context_set_handle (MonoAppContextHandle new_context);
-
G_END_DECLS
#endif /* __MONO_HANDLE_H__ */
#ifndef DISABLE_SOCKETS
ICALL_TYPE(NDNS, "System.Net.Dns", NDNS_1)
-ICALL(NDNS_1, "GetHostByAddr_internal(string,string&,string[]&,string[]&,int)", ves_icall_System_Net_Dns_GetHostByAddr_internal)
-ICALL(NDNS_2, "GetHostByName_internal(string,string&,string[]&,string[]&,int)", ves_icall_System_Net_Dns_GetHostByName_internal)
-ICALL(NDNS_3, "GetHostName_internal(string&)", ves_icall_System_Net_Dns_GetHostName_internal)
+HANDLES(ICALL(NDNS_1, "GetHostByAddr_internal(string,string&,string[]&,string[]&,int)", ves_icall_System_Net_Dns_GetHostByAddr_internal))
+HANDLES(ICALL(NDNS_2, "GetHostByName_internal(string,string&,string[]&,string[]&,int)", ves_icall_System_Net_Dns_GetHostByName_internal))
+HANDLES(ICALL(NDNS_3, "GetHostName_internal(string&)", ves_icall_System_Net_Dns_GetHostName_internal))
#if defined(PLATFORM_MACOSX) || defined(PLATFORM_BSD)
ICALL_TYPE(MAC_IFACE_PROPS, "System.Net.NetworkInformation.MacOsIPInterfaceProperties", MAC_IFACE_PROPS_1)
#endif
ICALL_TYPE(SOCK, "System.Net.Sockets.Socket", SOCK_1)
-ICALL(SOCK_1, "Accept_internal(intptr,int&,bool)", ves_icall_System_Net_Sockets_Socket_Accept_internal)
-ICALL(SOCK_2, "Available_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Available_internal)
-ICALL(SOCK_3, "Bind_internal(intptr,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_Bind_internal)
-ICALL(SOCK_4, "Blocking_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Blocking_internal)
-ICALL(SOCK_5, "Close_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Close_internal)
-ICALL(SOCK_6, "Connect_internal(intptr,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_Connect_internal)
-ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal)
-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)
-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)
-ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_IOControl_internal)
-ICALL(SOCK_9, "Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal)
-ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal)
-ICALL(SOCK_11, "Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal)
-ICALL(SOCK_13, "ReceiveFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&,bool)", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal)
-ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal)
-ICALL(SOCK_12, "Receive_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_internal)
-ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal)
-ICALL(SOCK_15, "Select_internal(System.Net.Sockets.Socket[]&,int,int&)", ves_icall_System_Net_Sockets_Socket_Select_internal)
-ICALL(SOCK_15a, "SendFile_internal(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendFile_internal)
-ICALL(SOCK_16, "SendTo_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendTo_internal)
-ICALL(SOCK_16a, "Send_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_array_internal)
-ICALL(SOCK_17, "Send_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_internal)
-ICALL(SOCK_18, "SetSocketOption_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&)", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal)
-ICALL(SOCK_19, "Shutdown_internal(intptr,System.Net.Sockets.SocketShutdown,int&)", ves_icall_System_Net_Sockets_Socket_Shutdown_internal)
-ICALL(SOCK_20, "Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,int&)", ves_icall_System_Net_Sockets_Socket_Socket_internal)
-ICALL(SOCK_20a, "SupportsPortReuse", ves_icall_System_Net_Sockets_Socket_SupportPortReuse)
-ICALL(SOCK_21a, "cancel_blocking_socket_operation", icall_cancel_blocking_socket_operation)
+HANDLES(ICALL(SOCK_1, "Accept_internal(intptr,int&,bool)", ves_icall_System_Net_Sockets_Socket_Accept_internal))
+HANDLES(ICALL(SOCK_2, "Available_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Available_internal))
+HANDLES(ICALL(SOCK_3, "Bind_internal(intptr,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_Bind_internal))
+HANDLES(ICALL(SOCK_4, "Blocking_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Blocking_internal))
+HANDLES(ICALL(SOCK_5, "Close_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Close_internal))
+HANDLES(ICALL(SOCK_6, "Connect_internal(intptr,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_Connect_internal))
+HANDLES(ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal))
+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))
+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))
+HANDLES(ICALL(SOCK_13, "ReceiveFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&,bool)", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal))
+HANDLES(ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal))
+HANDLES(ICALL(SOCK_12, "Receive_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_internal))
+HANDLES(ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal))
+HANDLES(ICALL(SOCK_15, "Select_internal(System.Net.Sockets.Socket[]&,int,int&)", ves_icall_System_Net_Sockets_Socket_Select_internal))
+HANDLES(ICALL(SOCK_15a, "SendFile_internal(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendFile_internal))
+HANDLES(ICALL(SOCK_16, "SendTo_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendTo_internal))
+HANDLES(ICALL(SOCK_16a, "Send_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_array_internal))
+HANDLES(ICALL(SOCK_17, "Send_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_internal))
+HANDLES(ICALL(SOCK_18, "SetSocketOption_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&)", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal))
+HANDLES(ICALL(SOCK_19, "Shutdown_internal(intptr,System.Net.Sockets.SocketShutdown,int&)", ves_icall_System_Net_Sockets_Socket_Shutdown_internal))
+HANDLES(ICALL(SOCK_20, "Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,int&)", ves_icall_System_Net_Sockets_Socket_Socket_internal))
+HANDLES(ICALL(SOCK_20a, "SupportsPortReuse", ves_icall_System_Net_Sockets_Socket_SupportPortReuse))
+HANDLES(ICALL(SOCK_21a, "cancel_blocking_socket_operation", icall_cancel_blocking_socket_operation))
ICALL_TYPE(SOCKEX, "System.Net.Sockets.SocketException", SOCKEX_1)
ICALL(SOCKEX_1, "WSAGetLastError_internal", ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal)
#endif
ICALL_TYPE(ACTS, "System.Runtime.Remoting.Activation.ActivationServices", ACTS_1)
-ICALL(ACTS_1, "AllocateUninitializedClassInstance", ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance)
-ICALL(ACTS_2, "EnableProxyActivation", ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation)
+HANDLES(ICALL(ACTS_1, "AllocateUninitializedClassInstance", ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance))
+HANDLES(ICALL(ACTS_2, "EnableProxyActivation", ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation))
ICALL_TYPE(CONTEXT, "System.Runtime.Remoting.Contexts.Context", CONTEXT_1)
HANDLES(ICALL(CONTEXT_1, "RegisterContext", ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext))
HANDLES(ICALL(REALP_2, "InternalGetTransparentProxy", ves_icall_Remoting_RealProxy_GetTransparentProxy))
ICALL_TYPE(REMSER, "System.Runtime.Remoting.RemotingServices", REMSER_0)
-ICALL(REMSER_0, "GetVirtualMethod", ves_icall_Remoting_RemotingServices_GetVirtualMethod)
+HANDLES(ICALL(REMSER_0, "GetVirtualMethod", ves_icall_Remoting_RemotingServices_GetVirtualMethod))
ICALL(REMSER_1, "InternalExecute", ves_icall_InternalExecute)
-ICALL(REMSER_2, "IsTransparentProxy", ves_icall_IsTransparentProxy)
+HANDLES(ICALL(REMSER_2, "IsTransparentProxy", ves_icall_IsTransparentProxy))
#endif
ICALL_TYPE(RVH, "System.Runtime.Versioning.VersioningHelper", RVH_1)
ICALL(MONIT_9, "try_enter_with_atomic_var", ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var)
ICALL_TYPE(MUTEX, "System.Threading.Mutex", MUTEX_1)
-ICALL(MUTEX_1, "CreateMutex_internal(bool,string,bool&)", ves_icall_System_Threading_Mutex_CreateMutex_internal)
-ICALL(MUTEX_2, "OpenMutex_internal(string,System.Security.AccessControl.MutexRights,System.IO.MonoIOError&)", ves_icall_System_Threading_Mutex_OpenMutex_internal)
+HANDLES(ICALL(MUTEX_1, "CreateMutex_internal(bool,string,bool&)", ves_icall_System_Threading_Mutex_CreateMutex_internal))
+HANDLES(ICALL(MUTEX_2, "OpenMutex_internal(string,System.Security.AccessControl.MutexRights,System.IO.MonoIOError&)", ves_icall_System_Threading_Mutex_OpenMutex_internal))
ICALL(MUTEX_3, "ReleaseMutex_internal(intptr)", ves_icall_System_Threading_Mutex_ReleaseMutex_internal)
ICALL_TYPE(NATIVEC, "System.Threading.NativeEventCalls", NATIVEC_1)
ICALL(NATIVEC_1, "CloseEvent_internal", ves_icall_System_Threading_Events_CloseEvent_internal)
-ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal)
-ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,int&)", ves_icall_System_Threading_Events_OpenEvent_internal)
+HANDLES(ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal))
+HANDLES(ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,int&)", ves_icall_System_Threading_Events_OpenEvent_internal))
ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal)
ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal)
}
#ifndef DISABLE_REMOTING
-ICALL_EXPORT MonoObject *
-ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
+static void
+internal_execute_field_getter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
{
- MonoError error;
- MonoDomain *domain = mono_object_domain (method);
- MonoMethod *m = method->method;
- MonoMethodSignature *sig = mono_method_signature (m);
+ error_init (error);
MonoArray *out_args;
- MonoObject *result;
- int i, j, outarg_count = 0;
-
- if (m->klass == mono_defaults.object_class) {
- if (!strcmp (m->name, "FieldGetter")) {
- MonoClass *k = mono_object_class (this_arg);
- MonoString *name;
- char *str;
+ MonoClass *k = mono_object_class (this_arg);
+ MonoString *name;
+ char *str;
- /* If this is a proxy, then it must be a CBO */
- if (mono_class_is_transparent_proxy (k)) {
- MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
- this_arg = tp->rp->unwrapped_server;
- g_assert (this_arg);
- k = mono_object_class (this_arg);
- }
+ /* If this is a proxy, then it must be a CBO */
+ if (mono_class_is_transparent_proxy (k)) {
+ MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
+ this_arg = tp->rp->unwrapped_server;
+ g_assert (this_arg);
+ k = mono_object_class (this_arg);
+ }
- name = mono_array_get (params, MonoString *, 1);
- str = mono_string_to_utf8_checked (name, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ name = mono_array_get (params, MonoString *, 1);
+ str = mono_string_to_utf8_checked (name, error);
+ return_if_nok (error);
- do {
- MonoClassField* field = mono_class_get_field_from_name (k, str);
- if (field) {
- g_free (str);
- MonoClass *field_klass = mono_class_from_mono_type (field->type);
- if (field_klass->valuetype) {
- result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- } else
- result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
-
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
- mono_array_setref (out_args, 0, result);
- return NULL;
- }
- k = k->parent;
- } while (k);
-
+ do {
+ MonoClassField* field = mono_class_get_field_from_name (k, str);
+ if (field) {
g_free (str);
- g_assert_not_reached ();
+ MonoClass *field_klass = mono_class_from_mono_type (field->type);
+ MonoObject *result;
+ if (field_klass->valuetype) {
+ result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, error);
+ return_if_nok (error);
+ } else
+ result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
+
+ out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
+ return_if_nok (error);
+ mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+ mono_array_setref (out_args, 0, result);
+ return;
+ }
+ k = k->parent;
+ } while (k);
- } else if (!strcmp (m->name, "FieldSetter")) {
- MonoClass *k = mono_object_class (this_arg);
- MonoString *name;
- guint32 size;
- gint32 align;
- char *str;
+ g_free (str);
+ g_assert_not_reached ();
+}
+
+static void
+internal_execute_field_setter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
+{
+ error_init (error);
+ MonoArray *out_args;
+ MonoClass *k = mono_object_class (this_arg);
+ MonoString *name;
+ guint32 size;
+ gint32 align;
+ char *str;
- /* If this is a proxy, then it must be a CBO */
- if (mono_class_is_transparent_proxy (k)) {
- MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
- this_arg = tp->rp->unwrapped_server;
- g_assert (this_arg);
- k = mono_object_class (this_arg);
- }
+ /* If this is a proxy, then it must be a CBO */
+ if (mono_class_is_transparent_proxy (k)) {
+ MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
+ this_arg = tp->rp->unwrapped_server;
+ g_assert (this_arg);
+ k = mono_object_class (this_arg);
+ }
- name = mono_array_get (params, MonoString *, 1);
- str = mono_string_to_utf8_checked (name, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ name = mono_array_get (params, MonoString *, 1);
+ str = mono_string_to_utf8_checked (name, error);
+ return_if_nok (error);
- do {
- MonoClassField* field = mono_class_get_field_from_name (k, str);
- if (field) {
- g_free (str);
- MonoClass *field_klass = mono_class_from_mono_type (field->type);
- MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
-
- if (field_klass->valuetype) {
- size = mono_type_size (field->type, &align);
- g_assert (size == mono_class_value_size (field_klass, NULL));
- mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
- } else {
- mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
- }
-
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+ do {
+ MonoClassField* field = mono_class_get_field_from_name (k, str);
+ if (field) {
+ g_free (str);
+ MonoClass *field_klass = mono_class_from_mono_type (field->type);
+ MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
- return NULL;
- }
+ if (field_klass->valuetype) {
+ size = mono_type_size (field->type, &align);
+ g_assert (size == mono_class_value_size (field_klass, NULL));
+ mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
+ } else {
+ mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
+ }
+
+ out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, error);
+ return_if_nok (error);
+ mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
+ return;
+ }
- k = k->parent;
- } while (k);
+ k = k->parent;
+ } while (k);
- g_free (str);
- g_assert_not_reached ();
+ g_free (str);
+ g_assert_not_reached ();
+}
+
+ICALL_EXPORT MonoObject *
+ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
+{
+ MonoError error;
+ MonoDomain *domain = mono_object_domain (method);
+ MonoMethod *m = method->method;
+ MonoMethodSignature *sig = mono_method_signature (m);
+ MonoArray *out_args;
+ MonoObject *result;
+ int i, j, outarg_count = 0;
+ if (m->klass == mono_defaults.object_class) {
+ if (!strcmp (m->name, "FieldGetter")) {
+ internal_execute_field_getter (domain, this_arg, params, outArgs, &error);
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ } else if (!strcmp (m->name, "FieldSetter")) {
+ internal_execute_field_setter (domain, this_arg, params, outArgs, &error);
+ mono_error_set_pending_exception (&error);
+ return NULL;
}
}
{
mono_environment_exitcode_set (result);
-/* FIXME: There are some cleanup hangs that should be worked out, but
- * if the program is going to exit, everything will be cleaned up when
- * NaCl exits anyway.
- */
-#ifndef __native_client__
if (!mono_runtime_try_shutdown ())
mono_thread_exit ();
mono_thread_suspend_all_other_threads ();
mono_runtime_quit ();
-#endif
/* we may need to do some cleanup here... */
exit (result);
#ifndef DISABLE_REMOTING
ICALL_EXPORT MonoBoolean
-ves_icall_IsTransparentProxy (MonoObject *proxy)
+ves_icall_IsTransparentProxy (MonoObjectHandle proxy, MonoError *error)
{
- if (!proxy)
+ error_init (error);
+ if (MONO_HANDLE_IS_NULL (proxy))
return 0;
- if (mono_object_is_transparent_proxy (proxy))
+ if (mono_class_is_transparent_proxy (mono_handle_class (proxy)))
return 1;
return 0;
}
-ICALL_EXPORT MonoReflectionMethod *
+ICALL_EXPORT MonoReflectionMethodHandle
ves_icall_Remoting_RemotingServices_GetVirtualMethod (
- MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
+ MonoReflectionTypeHandle rtype, MonoReflectionMethodHandle rmethod, MonoError *error)
{
- MonoReflectionMethod *ret = NULL;
- MonoError error;
-
- MonoClass *klass;
- MonoMethod *method;
- MonoMethod **vtable;
- MonoMethod *res = NULL;
+ MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- MONO_CHECK_ARG_NULL (rtype, NULL);
- MONO_CHECK_ARG_NULL (rmethod, NULL);
+ error_init (error);
+ if (MONO_HANDLE_IS_NULL (rtype)) {
+ mono_error_set_argument_null (error, "type", "");
+ return ret;
+ }
+ if (MONO_HANDLE_IS_NULL (rmethod)) {
+ mono_error_set_argument_null (error, "method", "");
+ return ret;
+ }
- method = rmethod->method;
- klass = mono_class_from_mono_type (rtype->type);
- mono_class_init_checked (klass, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ MonoMethod *method = MONO_HANDLE_GETVAL (rmethod, method);
+ MonoType *type = MONO_HANDLE_GETVAL (rtype, type);
+ MonoClass *klass = mono_class_from_mono_type (type);
+ mono_class_init_checked (klass, error);
+ return_val_if_nok (error, ret);
if (MONO_CLASS_IS_INTERFACE (klass))
- return NULL;
+ return ret;
if (method->flags & METHOD_ATTRIBUTE_STATIC)
- return NULL;
+ return ret;
if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
- return rmethod;
- else
- return NULL;
+ ret = rmethod;
+ return ret;
}
mono_class_setup_vtable (klass);
- vtable = klass->vtable;
+ MonoMethod **vtable = klass->vtable;
+ MonoMethod *res = NULL;
if (mono_class_is_interface (method->klass)) {
gboolean variance_used = FALSE;
/*MS fails with variant interfaces but it's the right thing to do anyway.*/
res = vtable [offs + method->slot];
} else {
if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
- return NULL;
+ return ret;
if (method->slot != -1)
res = vtable [method->slot];
}
if (!res)
- return NULL;
+ return ret;
- ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
- mono_error_set_pending_exception (&error);
+ ret = mono_method_get_object_handle (mono_domain_get (), res, NULL, error);
return ret;
}
ICALL_EXPORT void
-ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
+ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
{
- MonoError error;
- MonoClass *klass;
- MonoVTable* vtable;
+ error_init (error);
- klass = mono_class_from_mono_type (type->type);
- vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
- if (!is_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
+ MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
+ MonoVTable *vtable = mono_class_vtable_full (mono_domain_get (), klass, error);
+ return_if_nok (error);
mono_vtable_set_is_remote (vtable, enable);
}
#else /* DISABLE_REMOTING */
ICALL_EXPORT void
-ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
+ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
{
+ error_init (error);
g_assert_not_reached ();
}
#endif
-ICALL_EXPORT MonoObject *
-ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
+ICALL_EXPORT MonoObjectHandle
+ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionTypeHandle type, MonoError *error)
{
- MonoError error;
- MonoClass *klass;
- MonoDomain *domain;
- MonoObject *ret;
+ error_init (error);
- domain = mono_object_domain (type);
- klass = mono_class_from_mono_type (type->type);
- mono_class_init_checked (klass, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
+ MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
+ mono_class_init_checked (klass, error);
+ return_val_if_nok (error, NULL_HANDLE);
if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
- mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
- return NULL;
+ mono_error_set_argument (error, "type", "Type cannot be instantiated");
+ return NULL_HANDLE;
}
if (klass->rank >= 1) {
g_assert (klass->rank == 1);
- ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
- mono_error_set_pending_exception (&error);
- return ret;
+ return MONO_HANDLE_CAST (MonoObject, mono_array_new_handle (domain, klass->element_class, 0, error));
} else {
- MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
- if (!is_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- /* Bypass remoting object creation check */
- ret = mono_object_new_alloc_specific_checked (vtable, &error);
- mono_error_set_pending_exception (&error);
+ MonoVTable *vtable = mono_class_vtable_full (domain, klass, error);
+ return_val_if_nok (error, NULL_HANDLE);
- return ret;
+ /* Bypass remoting object creation check */
+ return MONO_HANDLE_NEW (MonoObject, mono_object_new_alloc_specific_checked (vtable, error));
}
}
iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
#endif
res.value = iter->args;
-#if defined(__native_client__) && SIZEOF_REGISTER == 8
- /* Values are stored as 8 byte register sized objects, but 'value'
- * is dereferenced as a pointer in other routines.
- */
- res.value = (char*)res.value + 4;
-#endif
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
if (arg_size <= sizeof (gpointer)) {
int dummy;
return result;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*
* mono_mb_emit_exception_marshal_directive:
}
mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", s);
}
-
-#endif /* !DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
guint
mono_type_to_ldind (MonoType *type)
return -1;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
static void
emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
emit_thread_force_interrupt_checkpoint (mb);
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static MonoAsyncResult *
return result;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
int
mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
return params_var;
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
static char*
mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
mb = mono_mb_new (get_wrapper_target_class (method->klass->image), name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
params_var = mono_mb_emit_save_args (mb, sig, FALSE);
mono_mb_emit_ldarg (mb, 0);
return res;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
void
mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
mono_mb_emit_byte (mb, CEE_RET);
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
/**
* mono_marshal_get_delegate_end_invoke:
mb = mono_mb_new (get_wrapper_target_class (method->klass->image), name, MONO_WRAPPER_DELEGATE_END_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
params_var = mono_mb_emit_save_args (mb, sig, FALSE);
mono_mb_emit_ldarg (mb, 0);
mb = mono_mb_new (get_wrapper_target_class (method->klass->image), name, MONO_WRAPPER_DELEGATE_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
void_ret = sig->ret->type == MONO_TYPE_VOID && !method->string_ctor;
/* allocate local 0 (object) */
mono_mb_emit_byte (mb, CEE_RET);
mb->skip_visibility = 1;
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
info = mono_wrapper_info_create (mb, subtype);
info->d.delegate_invoke.method = method;
return mono_metadata_signature_equal (sig1, sig2);
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*
* emit_invoke_call:
/* to make it work with our special string constructors */
if (!string_dummy) {
+ MonoError error;
MONO_GC_REGISTER_ROOT_SINGLE (string_dummy, MONO_ROOT_SOURCE_MARSHAL, "dummy marshal string");
- string_dummy = mono_string_new_wrapper ("dummy");
+ string_dummy = mono_string_new_checked (mono_get_root_domain (), "dummy", &error);
+ mono_error_assert_ok (&error);
}
if (virtual_) {
mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
param_names [0] = "this";
param_names [1] = "params";
param_names [2] = "exc";
#endif
if (need_direct_wrapper) {
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->skip_visibility = 1;
#endif
info = mono_wrapper_info_create (mb, virtual_ ? WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL : WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_RUNTIME_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* allocate local 0 (object) tmp */
mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
/* allocate local 1 (object) exc */
mono_mb_patch_branch (mb, pos);
//mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_RET);
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_RUNTIME_INVOKE);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
param_names [0] = "this";
param_names [1] = "params";
param_names [2] = "exc";
return res;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
static void
mono_mb_emit_auto_layout_exception (MonoMethodBuilder *mb, MonoClass *klass)
{
else
csig2 = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (sig->hasthis)
mono_mb_emit_byte (mb, CEE_LDARG_0);
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
if (action == MARSHAL_ACTION_CONV_IN && t->type == MONO_TYPE_VALUETYPE)
*conv_arg_type = &mono_defaults.int_class->byval_arg;
return conv_arg;
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodBuilder *mb = m->mb;
switch (action) {
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodBuilder *mb = m->mb;
MonoClass *klass, *date_time_class;
int pos = 0, pos2;
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
switch (action) {
case MARSHAL_ACTION_CONV_IN:
*conv_arg_type = &mono_defaults.int_class->byval_arg;
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
if (action == MARSHAL_ACTION_CONV_IN)
*conv_arg_type = &mono_defaults.int_class->byval_arg;
#else
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
if (action == MARSHAL_ACTION_CONV_IN)
*conv_arg_type = &mono_defaults.int_class->byval_arg;
#else
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
if (action == MARSHAL_ACTION_CONV_IN)
*conv_arg_type = &mono_defaults.int_class->byval_arg;
#else
return conv_arg;
}
-#ifndef DISABLE_JIT
-
+#ifdef HAVE_ONLINE_VES
#ifndef DISABLE_COM
static int
}
#endif /* DISABLE_COM */
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
static gboolean
mono_pinvoke_is_unicode (MonoMethodPInvoke *piinfo)
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
switch (action) {
case MARSHAL_ACTION_CONV_IN:
*conv_arg_type = &mono_defaults.object_class->byval_arg;
int conv_arg, MonoType **conv_arg_type,
MarshalAction action)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
switch (action) {
case MARSHAL_ACTION_CONV_IN:
if (t->byref)
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodBuilder *mb = m->mb;
switch (action) {
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodBuilder *mb = m->mb;
switch (action) {
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodBuilder *mb = m->mb;
switch (action) {
return emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
-#if !defined(DISABLE_COM) && !defined(DISABLE_JIT)
+#if !defined(DISABLE_COM) && defined(HAVE_ONLINE_VES)
if (spec && spec->native == MONO_NATIVE_STRUCT)
return emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
#endif
/* Wrap the argument in an object handle, pass the handle to the icall,
write the value out from the handle when the icall returns */
ICALL_HANDLES_WRAP_OBJ_INOUT,
+ /* Initialized an object handle to null, pass to the icalls,
+ write the value out from the handle when the icall returns */
+ ICALL_HANDLES_WRAP_OBJ_OUT,
/* Wrap the argument (a valuetype reference) in a handle to pin its enclosing object,
but pass the raw reference to the icall */
ICALL_HANDLES_WRAP_VALUETYPE_REF,
signature_param_uses_handles (MonoMethodSignature *sig, int param)
{
if (MONO_TYPE_IS_REFERENCE (sig->params [param])) {
- return mono_signature_param_is_out (sig, param) ? ICALL_HANDLES_WRAP_OBJ_INOUT : ICALL_HANDLES_WRAP_OBJ;
+ if (mono_signature_param_is_out (sig, param))
+ return ICALL_HANDLES_WRAP_OBJ_OUT;
+ else if (mono_type_is_byref (sig->params [param]))
+ return ICALL_HANDLES_WRAP_OBJ_INOUT;
+ else
+ return ICALL_HANDLES_WRAP_OBJ;
} else if (mono_type_is_byref (sig->params [param]))
return ICALL_HANDLES_WRAP_VALUETYPE_REF;
else
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/**
* mono_marshal_emit_native_wrapper:
* \param image the image to use for looking up custom marshallers
mono_mb_emit_byte (mb, CEE_RET);
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
/**
* mono_marshal_get_native_wrapper:
/* create a wrapper to preserve .ctor in stack trace */
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_MANAGED);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_mb_emit_byte (mb, CEE_LDARG_0);
for (i = 1; i <= csig->param_count; i++)
mono_mb_emit_ldarg (mb, i);
* registered in the runtime doing the AOT compilation.
*/
if (!piinfo->addr && !aot) {
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_mb_emit_exception (mb, exc_class, exc_arg);
#endif
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
if (method->string_ctor)
csig->ret = &mono_defaults.string_class->byval_arg;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
// FIXME:
MonoClass *handle_stack_mark_class;
MonoClass *error_class;
switch (w) {
case ICALL_HANDLES_WRAP_OBJ:
case ICALL_HANDLES_WRAP_OBJ_INOUT:
+ case ICALL_HANDLES_WRAP_OBJ_OUT:
ret->params [i] = mono_class_get_byref_type (mono_class_from_mono_type(csig->params[i]));
- if (w == ICALL_HANDLES_WRAP_OBJ_INOUT)
+ if (w == ICALL_HANDLES_WRAP_OBJ_OUT || w == ICALL_HANDLES_WRAP_OBJ_INOUT)
save_handles_to_locals = TRUE;
break;
case ICALL_HANDLES_WRAP_NONE:
handles_locals [j].handle = -1;
break;
case ICALL_HANDLES_WRAP_OBJ_INOUT:
+ case ICALL_HANDLES_WRAP_OBJ_OUT:
handles_locals [j].handle = mono_mb_add_local (mb, sig->params [i]);
break;
default:
mono_mb_emit_icall (mb, mono_icall_handle_new);
break;
case ICALL_HANDLES_WRAP_OBJ_INOUT:
- /* handleI = argI = mono_handle_new (NULL) */
- mono_mb_emit_byte (mb, CEE_LDNULL);
+ case ICALL_HANDLES_WRAP_OBJ_OUT:
+ /* if inout:
+ * handleI = argI = mono_handle_new (*argI_raw)
+ * otherwise:
+ * handleI = argI = mono_handle_new (NULL)
+ */
+ if (handles_locals[j].wrap == ICALL_HANDLES_WRAP_OBJ_INOUT) {
+ mono_mb_emit_ldarg (mb, j);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ } else
+ mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_icall (mb, mono_icall_handle_new);
/* tmp = argI */
mono_mb_emit_byte (mb, CEE_DUP);
case ICALL_HANDLES_WRAP_VALUETYPE_REF:
break;
case ICALL_HANDLES_WRAP_OBJ_INOUT:
+ case ICALL_HANDLES_WRAP_OBJ_OUT:
/* *argI_raw = MONO_HANDLE_RAW (handleI) */
/* argI_raw */
if (!aot)
g_assert (piinfo->addr);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
mono_method_get_marshal_info (method, mspecs);
info, NULL);
mono_mb_free (mb);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
for (i = sig->param_count; i >= 0; i--)
if (mspecs [i])
mono_metadata_free_marshal_spec (mspecs [i]);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
mb->method->save_lmf = 1;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, FALSE, TRUE, FALSE);
#endif
mb = mono_mb_new (invoke->klass, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
mb->method->save_lmf = 1;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, NULL, FALSE, TRUE, TRUE);
#endif
void
mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, uint32_t target_handle)
{
-#ifdef DISABLE_JIT
+#ifndef HAVE_ONLINE_VES
MonoMethodSignature *sig, *csig;
int i;
mb, csig, sig->param_count + 16,
info, NULL);
} else {
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->dynamic = TRUE;
#endif
res = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->dynamic = TRUE;
#endif
method = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_MANAGED);
param_count = sig->param_count + sig->hasthis;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
for (i = 0; i < param_count; i++)
mono_mb_emit_ldarg (mb, i);
return compiled_ptr;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*
* The code directly following this is the cache hit, value positive branch
mono_mb_emit_icall (mb, mono_marshal_isinst_with_cache);
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
/**
* mono_marshal_get_castclass_with_cache:
sig->ret = &mono_defaults.object_class->byval_arg;
sig->pinvoke = 0;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position,
&return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb);
invalid_cast_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
mono_mb_patch_branch (mb, return_null_pos);
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_byte (mb, CEE_RET);
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_CASTCLASS_WITH_CACHE);
res = mono_mb_create (mb, sig, 8, info);
sig->ret = &mono_defaults.object_class->byval_arg;
sig->pinvoke = 0;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position,
&return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb);
// Return the object gotten via the slow path.
mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (klass->blittable) {
mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_byte (mb, CEE_LDARG_0);
mb = mono_mb_new (klass, "PtrToStructure", MONO_WRAPPER_UNKNOWN);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (klass->blittable) {
mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_ldflda (mb, sizeof (MonoObject));
}
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNKNOWN);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_mb_emit_exception_full (mb, "System", "ExecutionEngineException", "Shouldn't be called.");
mono_mb_emit_byte (mb, CEE_RET);
#endif
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.synchronized.method = method;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->skip_visibility = 1;
/* result */
if (!MONO_TYPE_IS_VOID (sig->ret))
if (method->klass->valuetype && !(method->flags & MONO_METHOD_ATTR_STATIC)) {
/* FIXME Is this really the best way to signal an error here? Isn't this called much later after class setup? -AK */
mono_class_set_type_load_failure (method->klass, "");
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* This will throw the type load exception when the wrapper is compiled */
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_op (mb, CEE_ISINST, method->klass);
return res;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* this */
this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
taken_local = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
mono_marshal_unlock ();
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* Push this or the type object */
if (method->flags & METHOD_ATTRIBUTE_STATIC) {
/* We have special handling for this in the JIT */
g_assert (sig->hasthis);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_icon (mb, sizeof (MonoObject));
mono_mb_emit_byte (mb, CEE_ADD);
return STELEMREF_CLASS;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
static void
load_array_element_address (MonoMethodBuilder *mb)
signature = sig;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
param_names [0] = "index";
param_names [1] = "value";
mono_mb_set_param_names (mb, param_names);
mono_mb_emit_byte (mb, CEE_RET);
g_assert (0);
}
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_VIRTUAL_STELEMREF);
info->d.virtual_stelemref.kind = kind;
res = mono_mb_create (mb, signature, 4, info);
sig->params [1] = &mono_defaults.int_class->byval_arg; /* this is a natural sized int */
sig->params [2] = &mono_defaults.object_class->byval_arg;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
vklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
array_slot_addr = mono_mb_add_local (mb, &mono_defaults.object_class->this_arg);
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
sig->ret = &mono_defaults.void_class->byval_arg;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*
* The body is generated by the JIT, we use a wrapper instead of a trampoline so EH works.
*/
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
sig->ret = &mono_defaults.void_class->byval_arg;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*
* The body is generated by the JIT, we use a wrapper instead of a trampoline so EH works.
*/
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_MANAGED);
g_free (name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
bounds = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
ind = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
realidx = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
mono_mb_emit_exception (mb, "IndexOutOfRangeException", NULL);
g_free (branch_positions);
-#endif /* DISABLE_JIT */
+#endif /* HAVE_ONLINE_VES */
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_ELEMENT_ADDR);
info->d.element_addr.rank = rank;
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNKNOWN);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* Call the method */
if (sig->hasthis)
mono_mb_emit_ldarg (mb, 0);
csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->generic_param_count = 0;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mono_mb_emit_ldarg (mb, 0);
for (i = 0; i < csig->param_count; i++)
mono_mb_emit_ldarg (mb, i + 1);
if (MONO_TYPE_ISSTRUCT (sig->ret))
csig->ret = &mono_defaults.object_class->byval_arg;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* local 0 (temp for exception object) */
mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
m->inline_info = 1;
m->wrapper_type = type;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->code_size = 40;
mb->code = (unsigned char *)g_malloc (mb->code_size);
mb->init_locals = TRUE;
void
mono_mb_free (MonoMethodBuilder *mb)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
GList *l;
for (l = mb->locals_list; l; l = l->next) {
MonoMethod *
mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
{
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
MonoMethodHeader *header;
#endif
MonoMethodWrapper *mw;
image = mb->method->klass->image;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (mb->dynamic) {
method = mb->method;
mw = (MonoMethodWrapper*)method;
else
method->name = mono_image_strdup (image, mb->name);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mw->header = header = (MonoMethodHeader *)
mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
#endif
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/* Free the locals list so mono_mb_free () doesn't free the types twice */
g_list_free (mb->locals_list);
mb->locals_list = NULL;
if (!signature->hasthis)
method->flags |= METHOD_ATTRIBUTE_STATIC;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (max_stack < 8)
max_stack = 8;
mw->method_data = data;
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/*{
static int total_code = 0;
static int total_alloc = 0;
return g_list_length ((GList *)mw->method_data);
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
/**
* mono_mb_add_local:
MonoMethod *method;
char *name;
gboolean no_dup_name;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
GList *locals_list;
int locals;
gboolean dynamic;
guint32
mono_mb_add_data (MonoMethodBuilder *mb, gpointer data);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
void
mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value);
mono_config_parse_file (mono_cfg);
g_free (mono_cfg);
-#if !defined(TARGET_WIN32) && !defined(__native_client__)
+#if !defined(TARGET_WIN32)
home = g_get_home_dir ();
user_cfg = g_strconcat (home, G_DIR_SEPARATOR_S, ".mono/config", NULL);
mono_config_parse_file (user_cfg);
+++ /dev/null
-/**
- * \file
- */
-
-#if defined(__native_client__)
-
-#include "nacl-stub.h"
-
-struct group *getgrnam(const char *name)
-{
- return NULL;
-}
-
-struct group *getgrgid(gid_t gid)
-{
- errno = EIO;
- return NULL;
-}
-
-int fsync(int fd)
-{
- errno = EINVAL;
- return -1;
-}
-
-#ifdef USE_NEWLIB
-dev_t makedev(int maj, int min)
-{
- return (maj)*256+(min);
-}
-
-int utime(const char *filename, const void *times)
-{
- errno = EACCES;
- return -1;
-}
-
-int kill(pid_t pid, int sig)
-{
- errno = EACCES;
- return -1;
-}
-
-int getrusage(int who, void *usage)
-{
- errno = EACCES;
- return -1;
-}
-
-int lstat(const char *path, struct stat *buf)
-{
- return stat (path, buf);
-}
-
-int getdtablesize(void)
-{
-#ifdef OPEN_MAX
- return OPEN_MAX;
-#else
- return 256;
-#endif
-}
-
-size_t getpagesize(void)
-{
-#ifdef PAGE_SIZE
- return PAGE_SIZE;
-#else
- return 4096;
-#endif
-}
-
-int sem_trywait(sem_t *sem) {
- g_assert_not_reached ();
- return -1;
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) {
- g_assert_not_reached ();
- return -1;
-}
-
-#endif
-
-#endif
CallType_OneWay = 3
} MonoCallType;
+/* MonoSafeHandle is in class-internals.h. */
+/* Safely access System.Net.Sockets.SafeSocketHandle from native code */
+TYPED_HANDLE_DECL (MonoSafeHandle);
+
/* This corresponds to System.Type */
struct _MonoReflectionType {
MonoObject object;
gpointer last;
};
+/* It's safe to access System.Threading.InternalThread from native code via a
+ * raw pointer because all instances should be pinned. But for uniformity of
+ * icall wrapping, let's declare a MonoInternalThreadHandle anyway.
+ */
+TYPED_HANDLE_DECL (MonoInternalThread);
+
struct _MonoThread {
MonoObject obj;
struct _MonoInternalThread *internal_thread;
MonoProperty *prop;
} CattrNamedArg;
+/* All MonoInternalThread instances should be pinned, so it's safe to use the raw ptr. However
+ * for uniformity, icall wrapping will make handles anyway. So this is the method for getting the payload.
+ */
+static inline MonoInternalThread*
+mono_internal_thread_handle_ptr (MonoInternalThreadHandle h)
+{
+ return MONO_HANDLE_RAW (h); /* Safe */
+}
+
gboolean mono_image_create_pefile (MonoReflectionModuleBuilder *module, gpointer file, MonoError *error);
guint32 mono_image_insert_string (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error);
guint32 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj, gboolean create_methodspec, gboolean register_token, MonoError *error);
DECL_OFFSET(SeqPointInfo, bp_addrs)
#endif
+#ifdef ENABLE_INTERPRETER
+DECL_OFFSET(InterpMethodArguments, ilen)
+DECL_OFFSET(InterpMethodArguments, iargs)
+DECL_OFFSET(InterpMethodArguments, flen)
+DECL_OFFSET(InterpMethodArguments, fargs)
+DECL_OFFSET(InterpMethodArguments, retval)
+DECL_OFFSET(InterpMethodArguments, is_float_ret)
+#endif
+
#endif //DISABLE_JIT_OFFSETS
#endif //USED_CROSS_COMPILER_OFFSETS
return sgen_is_critical_method (method);
}
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
static void
emit_nursery_check (MonoMethodBuilder *mb, int *nursery_check_return_labels, gboolean is_concurrent)
else
mb = mono_mb_new (mono_defaults.object_class, "wbarrier_noconc", MONO_WRAPPER_WRITE_BARRIER);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
#ifdef MANAGED_WBARRIER
emit_nursery_check (mb, nursery_check_labels, is_concurrent);
/*
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ALLOC);
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
if (slowpath) {
switch (atype) {
case ATYPE_NORMAL:
info->d.alloc.gc_name = "sgen";
info->d.alloc.alloc_type = atype;
-#ifndef DISABLE_JIT
+#ifdef HAVE_ONLINE_VES
mb->init_locals = FALSE;
#endif
goto leave;
g_assert (base);
gint32 rank = MONO_HANDLE_GETVAL (sre_array, rank);
- if (rank == 0) //single dimentional array
- result = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
- else
- result = &mono_bounded_array_class_get (mono_class_from_mono_type (base), rank, TRUE)->byval_arg;
+ MonoClass *eclass = mono_class_from_mono_type (base);
+ result = mono_image_new0 (eclass->image, MonoType, 1);
+ if (rank == 0) {
+ result->type = MONO_TYPE_SZARRAY;
+ result->data.klass = eclass;
+ } else {
+ MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType));
+ result->type = MONO_TYPE_ARRAY;
+ result->data.array = at;
+ at->eklass = eclass;
+ at->rank = rank;
+ }
MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
} else if (is_sre_byref (klass)) {
MonoReflectionDerivedTypeHandle sre_byref = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
gboolean
mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
{
-#ifdef __native_client__
- return FALSE;
-#endif
-
abort_appdomain_data user_data;
gint64 start_time;
int orig_timeout = timeout;
#include "w32error.h"
#include "w32handle-namespace.h"
+#include "mono/utils/mono-error-internals.h"
#include "mono/utils/mono-logger-internals.h"
+#include "mono/metadata/handle.h"
+#include "mono/metadata/object-internals.h"
#include "mono/metadata/w32handle.h"
#define MAX_PATH 260
+static gpointer
+mono_w32event_create_full (MonoBoolean manual, MonoBoolean initial, const gchar *name, gint32 *err);
+
+static gpointer
+mono_w32event_open (const gchar *utf8_name, gint32 rights G_GNUC_UNUSED, gint32 *error);
+
typedef struct {
gboolean manual;
guint32 set_count;
MonoW32HandleNamespace sharedns;
};
+static void event_handle_signal (gpointer handle, MonoW32HandleType type, MonoW32HandleEvent *event_handle)
+{
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: signalling %s handle %p",
+ __func__, mono_w32handle_get_typename (type), handle);
+
+ if (!event_handle->manual) {
+ event_handle->set_count = 1;
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+ } else {
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+ }
+}
+
static gboolean event_handle_own (gpointer handle, MonoW32HandleType type, gboolean *abandoned)
{
MonoW32HandleEvent *event_handle;
return TRUE;
}
-static void event_signal(gpointer handle)
+static void event_signal(gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Events_SetEvent_internal (handle);
+ event_handle_signal (handle, MONO_W32HANDLE_EVENT, (MonoW32HandleEvent*) handle_specific);
}
static gboolean event_own (gpointer handle, gboolean *abandoned)
return event_handle_own (handle, MONO_W32HANDLE_EVENT, abandoned);
}
-static void namedevent_signal (gpointer handle)
+static void namedevent_signal (gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Events_SetEvent_internal (handle);
+ event_handle_signal (handle, MONO_W32HANDLE_NAMEDEVENT, (MonoW32HandleEvent*) handle_specific);
}
/* NB, always called with the shared handle lock held */
gpointer handle;
gint32 error;
- handle = ves_icall_System_Threading_Events_CreateEvent_internal (manual, initial, NULL, &error);
+ handle = mono_w32event_create_full (manual, initial, NULL, &error);
if (error != ERROR_SUCCESS)
g_assert (!handle);
return event_handle_create (&event_handle, MONO_W32HANDLE_EVENT, manual, initial);
}
-static gpointer namedevent_create (gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
+static gpointer namedevent_create (gboolean manual, gboolean initial, const gchar *utf8_name G_GNUC_UNUSED)
{
gpointer handle;
- gchar *utf8_name;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
__func__, mono_w32handle_get_typename (MONO_W32HANDLE_NAMEDEVENT));
/* w32 seems to guarantee that opening named objects can't race each other */
mono_w32handle_namespace_lock ();
- glong utf8_len = 0;
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, &utf8_len, NULL);
+ glong utf8_len = strlen (utf8_name);
handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
handle = event_handle_create ((MonoW32HandleEvent*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
}
- g_free (utf8_name);
-
mono_w32handle_namespace_unlock ();
return handle;
}
gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+mono_w32event_create_full (MonoBoolean manual, MonoBoolean initial, const gchar *name, gint32 *error)
{
gpointer event;
* was freshly created */
mono_w32error_set_last (ERROR_SUCCESS);
- event = name ? namedevent_create (manual, initial, mono_string_chars (name)) : event_create (manual, initial);
+ event = name ? namedevent_create (manual, initial, name) : event_create (manual, initial);
*error = mono_w32error_get_last ();
return event;
}
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error)
+{
+ error_init (error);
+ gchar *utf8_name = mono_string_handle_to_utf8 (name, error);
+ return_val_if_nok (error, NULL);
+ gpointer result = mono_w32event_create_full (manual, initial, utf8_name, err);
+ g_free (utf8_name);
+ return result;
+}
+
gboolean
ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
{
}
gpointer
-ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoStringHandle name, gint32 rights G_GNUC_UNUSED, gint32 *err, MonoError *error)
{
- gpointer handle;
- gchar *utf8_name;
+ error_init (error);
+ gchar *utf8_name = mono_string_handle_to_utf8 (name, error);
+ return_val_if_nok (error, NULL);
+ gpointer handle = mono_w32event_open (utf8_name, rights, err);
+ g_free (utf8_name);
+ return handle;
+}
+gpointer
+mono_w32event_open (const gchar *utf8_name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+{
+ gpointer handle;
*error = ERROR_SUCCESS;
/* w32 seems to guarantee that opening named objects can't race each other */
mono_w32handle_namespace_lock ();
- utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name);
handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle);
cleanup:
- g_free (utf8_name);
-
mono_w32handle_namespace_unlock ();
return handle;
#include <windows.h>
#include <winbase.h>
+#include <mono/metadata/handle.h>
+#include <mono/utils/mono-error-internals.h>
void
mono_w32event_init (void)
}
gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error)
{
gpointer event;
- event = CreateEvent (NULL, manual, initial, name ? mono_string_chars (name) : NULL);
-
- *error = GetLastError ();
+ error_init (error);
+
+ uint32_t gchandle = 0;
+ gunichar2 *uniname = NULL;
+ if (!MONO_HANDLE_IS_NULL (name))
+ uniname = mono_string_handle_pin_chars (name, &gchandle);
+ MONO_ENTER_GC_SAFE;
+ event = CreateEvent (NULL, manual, initial, uniname);
+ *err = GetLastError ();
+ MONO_EXIT_GC_SAFE;
+ if (gchandle)
+ mono_gchandle_free (gchandle);
return event;
}
}
gpointer
-ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error)
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error)
{
gpointer handle;
- *error = ERROR_SUCCESS;
+ error_init (error);
+
+ *err = ERROR_SUCCESS;
+
+ uint32_t gchandle = 0;
+ gunichar2 *uniname = NULL;
- handle = OpenEvent (rights, FALSE, mono_string_chars (name));
+ if (!MONO_HANDLE_IS_NULL (name))
+ uniname = mono_string_handle_pin_chars (name, &gchandle);
+
+ MONO_ENTER_GC_SAFE;
+ handle = OpenEvent (rights, FALSE, uniname);
if (!handle)
- *error = GetLastError ();
+ *err = GetLastError ();
+ MONO_EXIT_GC_SAFE;
+
+ if (gchandle)
+ mono_gchandle_free (gchandle);
return handle;
}
#include <glib.h>
#include "object.h"
+#include "object-internals.h"
#include "w32handle-namespace.h"
void
mono_w32event_reset (gpointer handle);
gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error);
gboolean
ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle);
ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle);
gpointer
-ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error);
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error);
typedef struct MonoW32HandleNamedEvent MonoW32HandleNamedEvent;
static gboolean
_wapi_lock_file_region (gint fd, off_t offset, off_t length)
{
-#if defined(__native_client__)
- printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
- // behave as below -- locks are not available
- return TRUE;
-#else
struct flock lock_data;
gint ret;
}
return TRUE;
-#endif /* __native_client__ */
}
static gboolean
_wapi_unlock_file_region (gint fd, off_t offset, off_t length)
{
-#if defined(__native_client__)
- printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
- return TRUE;
-#else
struct flock lock_data;
gint ret;
}
return TRUE;
-#endif /* __native_client__ */
}
static void file_close (gpointer handle, gpointer data);
}
#endif
-/* Native Client has no ftruncate function, even in standalone sel_ldr. */
-#ifndef __native_client__
/* always truncate, because the extend write() adds an extra
* byte to the end of the file
*/
_wapi_set_last_error_from_errno ();
return(FALSE);
}
-#endif
return(TRUE);
}
return(INVALID_HANDLE_VALUE);
}
-#ifdef __native_client__
- /* Workaround: Native Client currently returns the same fake inode
- * for all files, so do a simple hash on the filename so we don't
- * use the same share info for each file.
- */
- statbuf.st_ino = g_str_hash(filename);
-#endif
if (share_allows_open (&statbuf, sharemode, fileaccess,
&file_handle.share_info) == FALSE) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd);
-#if !defined(__native_client__)
/* Check if fd is valid */
do {
flags = fcntl(fd, F_GETFL);
file_handle.fileaccess = 0;
break;
}
-#else
- /*
- * fcntl will return -1 in nacl, as there is no real file system API.
- * Yet, standard streams are available.
- */
- file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
-#endif
file_handle.fd = fd;
file_handle.filename = g_strdup(name);
goto retry;
}
-#ifndef __native_client__
result = _wapi_lstat (filename, &linkbuf);
if (result != 0) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
g_free (filename);
goto retry;
}
-#endif
utf8_filename = mono_utf8_from_external (filename);
if (utf8_filename == NULL) {
else
create_time = buf.st_ctime;
-#ifdef __native_client__
- find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
-#else
find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
-#endif
time_t_to_filetime (create_time, &find_data->ftCreationTime);
time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
return (INVALID_FILE_ATTRIBUTES);
}
-#ifndef __native_client__
result = _wapi_lstat (utf8_name, &linkbuf);
if (result != 0) {
_wapi_set_last_path_error_from_errno (NULL, utf8_name);
g_free (utf8_name);
return (INVALID_FILE_ATTRIBUTES);
}
-#endif
-#ifdef __native_client__
- ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
-#else
ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
-#endif
g_free (utf8_name);
glong count;
gsize bytes;
-#ifdef __native_client__
- gchar *path = g_get_current_dir ();
- if (length < strlen(path) + 1 || path == NULL)
- return 0;
- memcpy (buffer, path, strlen(path) + 1);
-#else
if (getcwd ((gchar*)buffer, length) == NULL) {
if (errno == ERANGE) { /*buffer length is not big enough */
gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
_wapi_set_last_error_from_errno ();
return 0;
}
-#endif
utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
count = (bytes/2)+1;
return (drive_type);
}
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
static gchar*
get_fstypename (gchar *utfpath)
{
typedef struct {
gpointer ret;
MonoW32HandleType type;
- gchar *name;
+ const gchar *name;
} NamespaceSearchHandleData;
static gboolean
}
gpointer
-mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name)
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, const gchar *name)
{
NamespaceSearchHandleData search_data;
mono_w32handle_namespace_unlock (void);
gpointer
-mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name);
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, const gchar *name);
#endif /* _MONO_METADATA_W32HANDLE_NAMESPACE_H_ */
type = handle_data->type;
if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
- handle_ops[type]->signal (handle);
+ handle_ops[type]->signal (handle, handle_data->specific);
}
}
void (*close)(gpointer handle, gpointer data);
/* mono_w32handle_signal_and_wait */
- void (*signal)(gpointer signal);
+ void (*signal)(gpointer signal, gpointer data);
/* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple,
* with the handle locked (shared handles aren't locked.)
MonoW32HandleNamespace sharedns;
};
+gpointer
+mono_w32mutex_open (const gchar* utf8_name, gint32 right G_GNUC_UNUSED, gint32 *error);
+
static void
thread_own_mutex (MonoInternalThread *internal, gpointer handle)
{
mono_w32handle_unref (handle);
}
+static void
+mutex_handle_signal (gpointer handle, MonoW32HandleType type, MonoW32HandleMutex *mutex_handle)
+{
+ pthread_t tid;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: signalling %s handle %p, tid: %p recursion: %d",
+ __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
+
+ tid = pthread_self ();
+
+ if (mutex_handle->abandoned) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p is abandoned",
+ __func__, mono_w32handle_get_typename (type), handle);
+ } else if (!pthread_equal (mutex_handle->tid, tid)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
+ __func__, mono_w32handle_get_typename (type), handle, (long)mutex_handle->tid, (long)tid);
+ } else {
+ /* OK, we own this mutex */
+ mutex_handle->recursion--;
+
+ if (mutex_handle->recursion == 0) {
+ thread_disown_mutex (mono_thread_internal_current (), handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p, tid: %p recusion : %d",
+ __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
+
+ mutex_handle->tid = 0;
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+ }
+ }
+}
+
static gboolean
mutex_handle_own (gpointer handle, MonoW32HandleType type, gboolean *abandoned)
{
}
}
-static void mutex_signal(gpointer handle)
+static void mutex_signal(gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+ mutex_handle_signal (handle, MONO_W32HANDLE_MUTEX, (MonoW32HandleMutex*) handle_specific);
}
static gboolean mutex_own (gpointer handle, gboolean *abandoned)
static gboolean mutex_is_owned (gpointer handle)
{
-
return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
}
-static void namedmutex_signal (gpointer handle)
+static void namedmutex_signal (gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+ mutex_handle_signal (handle, MONO_W32HANDLE_NAMEDMUTEX, (MonoW32HandleMutex*) handle_specific);
}
/* NB, always called with the shared handle lock held */
return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
}
-static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
+static gpointer namedmutex_create (gboolean owned, const gchar *utf8_name)
{
gpointer handle;
- gchar *utf8_name;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
__func__, mono_w32handle_get_typename (MONO_W32HANDLE_NAMEDMUTEX));
/* w32 seems to guarantee that opening named objects can't race each other */
mono_w32handle_namespace_lock ();
- glong utf8_len = 0;
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, &utf8_len, NULL);
+ glong utf8_len = strlen (utf8_name);
handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
handle = mutex_handle_create ((MonoW32HandleMutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned);
}
- g_free (utf8_name);
-
mono_w32handle_namespace_unlock ();
return handle;
}
gpointer
-ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoStringHandle name, MonoBoolean *created, MonoError *error)
{
gpointer mutex;
+ error_init (error);
*created = TRUE;
/* Need to blow away any old errors here, because code tests
* was freshly created */
mono_w32error_set_last (ERROR_SUCCESS);
- if (!name) {
+ if (MONO_HANDLE_IS_NULL (name)) {
mutex = mutex_create (owned);
} else {
- mutex = namedmutex_create (owned, mono_string_chars (name));
+ gchar *utf8_name = mono_string_handle_to_utf8 (name, error);
+ return_val_if_nok (error, NULL);
+
+ mutex = namedmutex_create (owned, utf8_name);
if (mono_w32error_get_last () == ERROR_ALREADY_EXISTS)
*created = FALSE;
+ g_free (utf8_name);
}
return mutex;
}
gpointer
-ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoStringHandle name, gint32 rights G_GNUC_UNUSED, gint32 *err, MonoError *error)
+{
+ error_init (error);
+ gchar *utf8_name = mono_string_handle_to_utf8 (name, error);
+ return_val_if_nok (error, NULL);
+ gpointer handle = mono_w32mutex_open (utf8_name, rights, err);
+ g_free (utf8_name);
+ return handle;
+}
+
+gpointer
+mono_w32mutex_open (const gchar* utf8_name, gint32 right G_GNUC_UNUSED, gint32 *error)
{
gpointer handle;
- gchar *utf8_name;
*error = ERROR_SUCCESS;
/* w32 seems to guarantee that opening named objects can't race each other */
mono_w32handle_namespace_lock ();
- utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]",
__func__, utf8_name);
__func__, handle);
cleanup:
- g_free (utf8_name);
-
mono_w32handle_namespace_unlock ();
return handle;
#include <windows.h>
#include <winbase.h>
+#include <mono/metadata/handle.h>
+#include <mono/utils/mono-error-internals.h>
+
void
mono_w32mutex_init (void)
}
gpointer
-ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoStringHandle name, MonoBoolean *created, MonoError *error)
{
HANDLE mutex;
+ error_init (error);
+
*created = TRUE;
- if (!name) {
+ if (MONO_HANDLE_IS_NULL (name)) {
+ MONO_ENTER_GC_SAFE;
mutex = CreateMutex (NULL, owned, NULL);
+ MONO_EXIT_GC_SAFE;
} else {
- mutex = CreateMutex (NULL, owned, mono_string_chars (name));
+ uint32_t gchandle;
+ gunichar2 *uniname = mono_string_handle_pin_chars (name, &gchandle);
+ MONO_ENTER_GC_SAFE;
+ mutex = CreateMutex (NULL, owned, uniname);
if (GetLastError () == ERROR_ALREADY_EXISTS)
*created = FALSE;
+ MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
}
return mutex;
}
gpointer
-ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error)
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error)
{
HANDLE ret;
- *error = ERROR_SUCCESS;
+ error_init (error);
+ *err = ERROR_SUCCESS;
- ret = OpenMutex (rights, FALSE, mono_string_chars (name));
+ uint32_t gchandle = 0;
+ gunichar2 *uniname = NULL;
+ if (!MONO_HANDLE_IS_NULL (name))
+ uniname = mono_string_handle_pin_chars (name, &gchandle);
+ MONO_ENTER_GC_SAFE;
+ ret = OpenMutex (rights, FALSE, uniname);
if (!ret)
- *error = GetLastError ();
+ *err = GetLastError ();
+ MONO_EXIT_GC_SAFE;
+ if (gchandle != 0)
+ mono_gchandle_free (gchandle);
return ret;
}
#include <glib.h>
#include "object.h"
+#include "object-internals.h"
#include "w32handle-namespace.h"
void
mono_w32mutex_init (void);
gpointer
-ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created);
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoStringHandle name, MonoBoolean *created, MonoError *error);
MonoBoolean
ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle);
gpointer
-ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error);
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error);
typedef struct MonoW32HandleNamedMutex MonoW32HandleNamedMutex;
MonoW32HandleNamespace sharedns;
};
+static void sem_handle_signal (gpointer handle, MonoW32HandleType type, MonoW32HandleSemaphore *sem_handle)
+{
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: signalling %s handle %p",
+ __func__, mono_w32handle_get_typename (type), handle);
+
+ /* No idea why max is signed, but thats the spec :-( */
+ if (sem_handle->val + 1 > (guint32)sem_handle->max) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
+ __func__, mono_w32handle_get_typename (type), handle, sem_handle->val, 1, sem_handle->max);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
+ __func__, mono_w32handle_get_typename (type), handle, sem_handle->val, 1, sem_handle->max);
+
+ sem_handle->val += 1;
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+ }
+}
+
static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type, gboolean *abandoned)
{
MonoW32HandleSemaphore *sem_handle;
return TRUE;
}
-static void sema_signal(gpointer handle)
+static void sema_signal(gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal(handle, 1, NULL);
+ sem_handle_signal (handle, MONO_W32HANDLE_SEM, (MonoW32HandleSemaphore*) handle_specific);
}
static gboolean sema_own (gpointer handle, gboolean *abandoned)
return sem_handle_own (handle, MONO_W32HANDLE_SEM, abandoned);
}
-static void namedsema_signal (gpointer handle)
+static void namedsema_signal (gpointer handle, gpointer handle_specific)
{
- ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (handle, 1, NULL);
+ sem_handle_signal (handle, MONO_W32HANDLE_NAMEDSEM, (MonoW32HandleSemaphore*) handle_specific);
}
/* NB, always called with the shared handle lock held */
}
gboolean
-ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto)
+ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error)
{
+ error_init (error);
#if defined (SO_REUSEPORT)
return TRUE;
#else
}
gboolean
-ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto)
+ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error)
{
+ error_init (error);
return TRUE;
}
#define LOGDEBUG(...)
/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
+static gboolean
+addrinfo_to_IPHostEntry_handles (MonoAddressInfo *info, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gboolean add_local_ips, MonoError *error);
+
+static MonoObjectHandle
+create_object_handle_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error);
+
+static struct sockaddr*
+create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error);
+
#ifdef HOST_WIN32
static SOCKET
}
gpointer
-ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObjectHandle this_obj, gint32 family, gint32 type, gint32 proto, gint32 *werror, MonoError *error)
{
SOCKET sock;
gint32 sock_family;
gint32 sock_proto;
gint32 sock_type;
+ error_init (error);
*werror = 0;
sock_family = convert_family ((MonoAddressFamily)family);
* file) is really an IntPtr which needs to be converted to a guint32.
*/
void
-ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror, MonoError *error)
{
LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock));
+ error_init (error);
*werror = 0;
/* Clear any pending work item from this socket if the underlying
}
gint32
-ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *werror, MonoError *error)
{
int ret;
guint64 amount;
+ error_init (error);
*werror = 0;
/* FIXME: this might require amount to be unsigned long. */
}
void
-ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *werror, MonoError *error)
{
int ret;
+ error_init (error);
*werror = 0;
ret = mono_w32socket_set_blocking (sock, block);
}
gpointer
-ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror, gboolean blocking, MonoError *error)
{
gboolean interrupted;
SOCKET newsock;
+ error_init (error);
*werror = 0;
mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
}
void
-ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog, gint32 *werror, MonoError *error)
{
int ret;
+ error_init (error);
*werror = 0;
MONO_ENTER_GC_SAFE;
}
#endif
-static MonoObject*
-create_object_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error)
+static MonoObjectHandle
+create_object_handle_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error)
{
MonoDomain *domain = mono_domain_get ();
- MonoObject *sockaddr_obj;
- MonoArray *data;
MonoAddressFamily family;
error_init (error);
/* Build a System.Net.SocketAddress object instance */
if (!domain->sockaddr_class)
domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
- sockaddr_obj = mono_object_new_checked (domain, domain->sockaddr_class, error);
- return_val_if_nok (error, NULL);
+ MonoObjectHandle sockaddr_obj = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, domain->sockaddr_class, error));
+ return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL));
/* Locate the SocketAddress data buffer in the object */
if (!domain->sockaddr_data_field) {
* the length of the entire sockaddr_in/in6, including
* sizeof (unsigned short) of the family */
/* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
- data = mono_array_new_cached (domain, mono_get_byte_class (), sa_size + 2, error);
- return_val_if_nok (error, NULL);
+ MonoArrayHandle data = mono_array_new_handle (domain, mono_get_byte_class (), sa_size + 2, error);
+ return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL));
/* The data buffer is laid out as follows:
* bytes 0 and 1 are the address family
family = convert_to_mono_family (saddr->sa_family);
if (family == AddressFamily_Unknown) {
*werror = WSAEAFNOSUPPORT;
- return NULL;
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
- mono_array_set (data, guint8, 0, family & 0x0FF);
- mono_array_set (data, guint8, 1, (family >> 8) & 0x0FF);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 0, family & 0x0FF);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 1, (family >> 8) & 0x0FF);
if (saddr->sa_family == AF_INET) {
struct sockaddr_in *sa_in = (struct sockaddr_in *)saddr;
int buffer_size = 8;
if (sa_size < buffer_size) {
- mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
- return NULL;
+ mono_error_set_generic_error (error, "System", "SystemException", "");
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
- mono_array_set (data, guint8, 2, (port>>8) & 0xff);
- mono_array_set (data, guint8, 3, (port) & 0xff);
- mono_array_set (data, guint8, 4, (address>>24) & 0xff);
- mono_array_set (data, guint8, 5, (address>>16) & 0xff);
- mono_array_set (data, guint8, 6, (address>>8) & 0xff);
- mono_array_set (data, guint8, 7, (address) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 2, (port>>8) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 3, (port) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 4, (address>>24) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 5, (address>>16) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 6, (address>>8) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 7, (address) & 0xff);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */
return sockaddr_obj;
}
guint16 port = ntohs (sa_in->sin6_port);
if (sa_size < buffer_size) {
- mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
- return NULL;
+ mono_error_set_generic_error (error, "System", "SystemException", "");
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
- mono_array_set (data, guint8, 2, (port>>8) & 0xff);
- mono_array_set (data, guint8, 3, (port) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 2, (port>>8) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 3, (port) & 0xff);
if (is_ipv4_mapped_any (&sa_in->sin6_addr)) {
// Map ::ffff:0:0 to :: (bug #5502)
for (i = 0; i < 16; i++)
- mono_array_set (data, guint8, 8 + i, 0);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 8 + i, 0);
} else {
for (i = 0; i < 16; i++) {
- mono_array_set (data, guint8, 8 + i,
- sa_in->sin6_addr.s6_addr [i]);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 8 + i,
+ sa_in->sin6_addr.s6_addr [i]);
}
}
- mono_array_set (data, guint8, 24, sa_in->sin6_scope_id & 0xff);
- mono_array_set (data, guint8, 25,
- (sa_in->sin6_scope_id >> 8) & 0xff);
- mono_array_set (data, guint8, 26,
- (sa_in->sin6_scope_id >> 16) & 0xff);
- mono_array_set (data, guint8, 27,
- (sa_in->sin6_scope_id >> 24) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 24, sa_in->sin6_scope_id & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 25,
+ (sa_in->sin6_scope_id >> 8) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 26,
+ (sa_in->sin6_scope_id >> 16) & 0xff);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, 27,
+ (sa_in->sin6_scope_id >> 24) & 0xff);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */
return sockaddr_obj;
}
int buffer_size = sa_size + 2;
for (i = 0; i < sa_size; i++)
- mono_array_set (data, guint8, i + 2, saddr->sa_data [i]);
+ MONO_HANDLE_ARRAY_SETVAL (data, guint8, i + 2, saddr->sa_data [i]);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
- mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */
+ mono_field_set_value (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */
return sockaddr_obj;
}
#endif
else {
*werror = WSAEAFNOSUPPORT;
- return NULL;
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
}
return size;
}
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *werror)
+MonoObjectHandle
+ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *werror, MonoError *error)
{
gchar *sa;
socklen_t salen;
int ret;
- MonoObject *result;
- MonoError error;
*werror = 0;
*werror = mono_w32socket_get_last_error ();
if (salen > 128)
g_free (sa);
- return NULL;
+ return NULL_HANDLE;
}
LOGDEBUG (g_message("%s: bound to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
- result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
+ MonoObjectHandle result = create_object_handle_from_sockaddr ((struct sockaddr *)sa, salen, werror, error);
if (salen > 128)
g_free (sa);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
return result;
}
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *werror)
+MonoObjectHandle
+ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *werror, MonoError *error)
{
gchar *sa;
socklen_t salen;
int ret;
- MonoObject *result;
- MonoError error;
+ error_init (error);
*werror = 0;
salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af));
if (salen == 0) {
*werror = WSAEAFNOSUPPORT;
- return NULL;
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
/* Note: linux returns just 2 for AF_UNIX. Always. */
*werror = mono_w32socket_get_last_error ();
if (salen > 128)
g_free (sa);
- return NULL;
+ return MONO_HANDLE_NEW (MonoObject, NULL);
}
LOGDEBUG (g_message("%s: connected to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
- result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
+ MonoObjectHandle result = create_object_handle_from_sockaddr ((struct sockaddr *)sa, salen, werror, error);
if (salen > 128)
g_free (sa);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
return result;
}
static struct sockaddr*
-create_sockaddr_from_object (MonoObject *saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error)
+create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error)
{
MonoDomain *domain = mono_domain_get ();
- MonoArray *data;
gint32 family;
int len;
g_assert (domain->sockaddr_data_length_field);
}
- data = *(MonoArray **)(((char *)saddr_obj) + domain->sockaddr_data_field->offset);
+ MonoArrayHandle data = MONO_HANDLE_NEW_GET_FIELD (saddr_obj, MonoArray, domain->sockaddr_data_field);
/* The data buffer is laid out as follows:
* byte 0 is the address family low byte
* UNIX:
* the rest is the file name
*/
- len = *(int *)(((char *)saddr_obj) + domain->sockaddr_data_length_field->offset);
+ len = MONO_HANDLE_GET_FIELD_VAL (saddr_obj, int, domain->sockaddr_data_length_field);
g_assert (len >= 2);
- family = convert_family ((MonoAddressFamily)(mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8)));
+ uint32_t gchandle;
+ guint8 *buf = MONO_ARRAY_HANDLE_PIN (data, guint8, 0, &gchandle);
+ family = convert_family ((MonoAddressFamily)(buf[0] + (buf[1] << 8)));
if (family == AF_INET) {
struct sockaddr_in *sa;
guint16 port;
guint32 address;
if (len < 8) {
- mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+ mono_error_set_generic_error (error, "System", "SystemException", "");
+ mono_gchandle_free (gchandle);
return NULL;
}
sa = g_new0 (struct sockaddr_in, 1);
- port = (mono_array_get (data, guint8, 2) << 8) +
- mono_array_get (data, guint8, 3);
- address = (mono_array_get (data, guint8, 4) << 24) +
- (mono_array_get (data, guint8, 5) << 16 ) +
- (mono_array_get (data, guint8, 6) << 8) +
- mono_array_get (data, guint8, 7);
+ port = (buf[2] << 8) + buf[3];
+ address = (buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7];
sa->sin_family = family;
sa->sin_addr.s_addr = htonl (address);
sa->sin_port = htons (port);
*sa_size = sizeof (struct sockaddr_in);
+ mono_gchandle_free (gchandle);
return (struct sockaddr *)sa;
}
#ifdef HAVE_STRUCT_SOCKADDR_IN6
guint32 scopeid;
if (len < 28) {
- mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+ mono_error_set_generic_error (error, "System", "SystemException", "");
+ mono_gchandle_free (gchandle);
return NULL;
}
sa = g_new0 (struct sockaddr_in6, 1);
- port = mono_array_get (data, guint8, 3) +
- (mono_array_get (data, guint8, 2) << 8);
- scopeid = mono_array_get (data, guint8, 24) +
- (mono_array_get (data, guint8, 25) << 8) +
- (mono_array_get (data, guint8, 26) << 16) +
- (mono_array_get (data, guint8, 27) << 24);
+ port = buf[3] + (buf[2] << 8);
+ scopeid = buf[24] + (buf[25] << 8) + (buf[26] << 16) + (buf[27] << 24);
sa->sin6_family = family;
sa->sin6_port = htons (port);
sa->sin6_scope_id = scopeid;
for (i = 0; i < 16; i++)
- sa->sin6_addr.s6_addr [i] = mono_array_get (data, guint8, 8 + i);
+ sa->sin6_addr.s6_addr [i] = buf[8 + i];
*sa_size = sizeof (struct sockaddr_in6);
+ mono_gchandle_free (gchandle);
return (struct sockaddr *)sa;
}
#endif
*/
if (len - 2 >= sizeof (sock_un->sun_path)) {
mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
+ mono_gchandle_free (gchandle);
return NULL;
}
sock_un->sun_family = family;
for (i = 0; i < len - 2; i++)
- sock_un->sun_path [i] = mono_array_get (data, guint8, i + 2);
+ sock_un->sun_path [i] = buf[i + 2];
*sa_size = len;
+ mono_gchandle_free (gchandle);
return (struct sockaddr *)sock_un;
}
#endif
else {
*werror = WSAEAFNOSUPPORT;
+ mono_gchandle_free (gchandle);
return 0;
}
}
void
-ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObject *sockaddr, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, MonoError *error)
{
- MonoError error;
struct sockaddr *sa;
socklen_t sa_size;
int ret;
+ error_init (error);
*werror = 0;
- sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
+ sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error);
if (*werror != 0)
return;
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
+ return_if_nok (error);
LOGDEBUG (g_message("%s: binding to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
MonoBoolean
ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode,
- gint timeout, gint32 *werror)
+ gint timeout, gint32 *werror, MonoError *error)
{
MonoInternalThread *thread = mono_thread_internal_current ();
mono_pollfd *pfds;
gboolean interrupted;
time_t start;
+ error_init (error);
*werror = 0;
pfds = g_new0 (mono_pollfd, 1);
}
void
-ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObject *sockaddr, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, gboolean blocking, MonoError *error)
{
- MonoError error;
struct sockaddr *sa;
socklen_t sa_size;
int ret;
gboolean interrupted;
+ error_init (error);
*werror = 0;
- sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
+ sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error);
if (*werror != 0)
return;
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
+ return_if_nok (error);
LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
void
-ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror, MonoError *error)
{
gboolean interrupted;
+ error_init (error);
+
LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__, sock, reuse));
mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
gint32
-ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
{
int ret;
- gchar *buf;
gint32 alen;
int recvflags = 0;
gboolean interrupted;
MonoInternalThread* curthread G_GNUC_UNUSED = mono_thread_internal_current ();
+ error_init (error);
*werror = 0;
- alen = mono_array_length (buffer);
+ alen = mono_array_handle_length (buffer);
if (offset > alen - count)
return 0;
- buf = mono_array_addr (buffer, gchar, offset);
-
recvflags = convert_socketflags (flags);
if (recvflags == -1) {
*werror = WSAEOPNOTSUPP;
if (interrupted)
return 0;
+ uint32_t gchandle;
+ gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_recv (sock, buf, count, recvflags, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
gint32
-ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArrayHandle buffers, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
{
int ret, count;
gboolean interrupted;
guint32 recv;
- WSABUF *wsabufs;
guint32 recvflags = 0;
+ error_init (error);
*werror = 0;
- wsabufs = mono_array_addr (buffers, WSABUF, 0);
- count = mono_array_length (buffers);
+ count = mono_array_handle_length (buffers);
recvflags = convert_socketflags (flags);
if (recvflags == -1) {
return 0;
}
+ uint32_t gchandle;
+ WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_recvbuffers (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
gint32
-ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, MonoObjectHandle sockaddr, gint32 *werror, gboolean blocking, MonoError *error)
{
- MonoError error;
int ret;
gchar *buf;
gint32 alen;
socklen_t sa_size;
gboolean interrupted;
+ error_init (error);
*werror = 0;
- alen = mono_array_length (buffer);
+ alen = mono_array_handle_length (buffer);
if (offset > alen - count)
return 0;
- sa = create_sockaddr_from_object (*sockaddr, &sa_size, werror, &error);
+ sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error);
if (*werror != 0)
return 0;
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
+ if (!is_ok (error))
return 0;
- }
-
- buf = mono_array_addr (buffer, gchar, offset);
recvflags = convert_socketflags (flags);
if (recvflags == -1) {
return 0;
}
+ uint32_t gchandle;
+ buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
* returned the remote address. All we can do is return null.
*/
if (sa_size) {
- *sockaddr = create_object_from_sockaddr (sa, sa_size, werror, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
+ MONO_HANDLE_ASSIGN (sockaddr, create_object_handle_from_sockaddr (sa, sa_size, werror, error));
+ if (!is_ok (error)) {
g_free (sa);
return 0;
}
} else {
- *sockaddr = NULL;
+ MONO_HANDLE_ASSIGN (sockaddr, MONO_HANDLE_NEW (MonoObject, NULL));
}
g_free (sa);
}
gint32
-ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
{
int ret;
- gchar *buf;
gint32 alen;
int sendflags = 0;
gboolean interrupted;
+ error_init (error);
*werror = 0;
- alen = mono_array_length (buffer);
+ alen = mono_array_handle_length (buffer);
if (offset > alen - count)
return 0;
LOGDEBUG (g_message("%s: alen: %d", __func__, alen));
- buf = mono_array_addr (buffer, gchar, offset);
-
LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
sendflags = convert_socketflags (flags);
return 0;
}
+ uint32_t gchandle;
+ gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_send (sock, buf, count, sendflags, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
gint32
-ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArrayHandle buffers, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
{
int ret, count;
guint32 sent;
- WSABUF *wsabufs;
guint32 sendflags = 0;
gboolean interrupted;
+ error_init (error);
*werror = 0;
- wsabufs = mono_array_addr (buffers, WSABUF, 0);
- count = mono_array_length (buffers);
+ count = mono_array_handle_length (buffers);
sendflags = convert_socketflags (flags);
if (sendflags == -1) {
return 0;
}
+ uint32_t gchandle;
+ WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_sendbuffers (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
gint32
-ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, MonoObjectHandle sockaddr, gint32 *werror, gboolean blocking, MonoError *error)
{
- MonoError error;
int ret;
- gchar *buf;
gint32 alen;
int sendflags = 0;
struct sockaddr *sa;
*werror = 0;
- alen = mono_array_length (buffer);
+ alen = mono_array_handle_length (buffer);
if (offset > alen - count) {
return 0;
}
- sa = create_sockaddr_from_object(sockaddr, &sa_size, werror, &error);
+ sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error);
if (*werror != 0)
return 0;
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return 0;
- }
+ return_val_if_nok (error, 0);
LOGDEBUG (g_message ("%s: alen: %d", __func__, alen));
- buf = mono_array_addr (buffer, gchar, offset);
-
LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
sendflags = convert_socketflags (flags);
return 0;
}
+ uint32_t gchandle;
+ gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_sendto (sock, buf, count, sendflags, sa, sa_size, blocking);
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
static SOCKET
-Socket_to_SOCKET (MonoObject *sockobj)
+Socket_to_SOCKET (MonoObjectHandle sockobj)
{
- MonoSafeHandle *safe_handle;
MonoClassField *field;
- field = mono_class_get_field_from_name (sockobj->vtable->klass, "m_Handle");
- safe_handle = ((MonoSafeHandle *)(*(gpointer *)(((char *)sockobj) + field->offset)));
+ field = mono_class_get_field_from_name (mono_handle_class (sockobj), "m_Handle");
+ MonoSafeHandleHandle safe_handle = MONO_HANDLE_NEW_GET_FIELD(sockobj, MonoSafeHandle, field);
- if (safe_handle == NULL)
+ if (MONO_HANDLE_IS_NULL (safe_handle))
return -1;
- return (SOCKET)safe_handle->handle;
+ return (SOCKET)MONO_HANDLE_GETVAL (safe_handle, handle);
}
#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
+static gboolean
+collect_pollfds_from_array (MonoArrayHandle sockets, int i, int nfds, mono_pollfd *pfds, int *idx, int *mode)
+{
+ HANDLE_FUNCTION_ENTER ();
+ gboolean result = TRUE;
+ MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, NULL);
+ MONO_HANDLE_ARRAY_GETREF (obj, sockets, i);
+ if (MONO_HANDLE_IS_NULL (obj)) {
+ (*mode)++;
+ goto leave;
+ }
+
+ if (*idx >= nfds) {
+ result = FALSE;
+ goto leave;
+ }
+
+ pfds [*idx].fd = Socket_to_SOCKET (obj);
+ pfds [*idx].events = (*mode == 0) ? MONO_POLLIN : (*mode == 1) ? MONO_POLLOUT : POLL_ERRORS;
+ (*idx)++;
+leave:
+ HANDLE_FUNCTION_RETURN_VAL (result);
+}
+
+static void
+set_socks_array_from_pollfds (MonoArrayHandle sockets, int i, mono_pollfd *pfds, int *ret, int *mode, MonoArrayHandle socks, int *idx)
+{
+ HANDLE_FUNCTION_ENTER ();
+ mono_pollfd *pfd;
+
+ MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, NULL);
+ MONO_HANDLE_ARRAY_GETREF (obj, sockets, i);
+ if (MONO_HANDLE_IS_NULL (obj)) {
+ (*mode)++;
+ (*idx)++;
+ goto leave;
+ }
+
+ pfd = &pfds [i - *mode];
+ if (pfd->revents == 0)
+ goto leave;
+
+ (*ret)--;
+ if (((*mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0)) ||
+ ((*mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0)) ||
+ ((pfd->revents & POLL_ERRORS) != 0)) {
+ MONO_HANDLE_ARRAY_SETREF (socks, *idx, obj);
+ (*idx)++;
+ }
+leave:
+ HANDLE_FUNCTION_RETURN ();
+}
+
void
-ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArrayHandle sockets, gint32 timeout, gint32 *werror, MonoError *error)
{
- MonoError error;
MonoInternalThread *thread = mono_thread_internal_current ();
- MonoObject *obj;
mono_pollfd *pfds;
int nfds, idx;
int ret;
int i, count;
int mode;
MonoClass *sock_arr_class;
- MonoArray *socks;
time_t start;
uintptr_t socks_size;
gboolean interrupted;
+ error_init (error);
*werror = 0;
/* *sockets -> READ, null, WRITE, null, ERROR, null */
- count = mono_array_length (*sockets);
+ count = mono_array_handle_length (sockets);
nfds = count - 3; /* NULL separators */
pfds = g_new0 (mono_pollfd, nfds);
mode = idx = 0;
for (i = 0; i < count; i++) {
- obj = mono_array_get (*sockets, MonoObject *, i);
- if (obj == NULL) {
- mode++;
- continue;
- }
-
- if (idx >= nfds) {
+ if (!collect_pollfds_from_array (sockets, i, nfds, pfds, &idx, &mode)) {
/* The socket array was bogus */
g_free (pfds);
*werror = WSAEFAULT;
return;
}
-
- pfds [idx].fd = Socket_to_SOCKET (obj);
- pfds [idx].events = (mode == 0) ? MONO_POLLIN : (mode == 1) ? MONO_POLLOUT : POLL_ERRORS;
- idx++;
}
timeout = (timeout >= 0) ? (timeout / 1000) : -1;
if (ret == -1 && errno == EINTR) {
if (mono_thread_test_state (thread, ThreadState_AbortRequested)) {
g_free (pfds);
- *sockets = NULL;
+ MONO_HANDLE_ASSIGN (sockets, MONO_HANDLE_NEW (MonoObject, NULL));
return;
}
if (ret == 0) {
g_free (pfds);
- *sockets = NULL;
+ MONO_HANDLE_ASSIGN (sockets, MONO_HANDLE_NEW (MonoObject, NULL));
return;
}
- sock_arr_class = ((MonoObject *)*sockets)->vtable->klass;
+ sock_arr_class = mono_handle_class (sockets);
socks_size = ((uintptr_t)ret) + 3; /* space for the NULL delimiters */
- socks = mono_array_new_full_checked (mono_domain_get (), sock_arr_class, &socks_size, NULL, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
+ MonoArrayHandle socks = MONO_HANDLE_NEW (MonoArray, mono_array_new_full_checked (mono_domain_get (), sock_arr_class, &socks_size, NULL, error));
+ if (!is_ok (error)) {
g_free (pfds);
return;
}
mode = idx = 0;
for (i = 0; i < count && ret > 0; i++) {
- mono_pollfd *pfd;
-
- obj = mono_array_get (*sockets, MonoObject *, i);
- if (obj == NULL) {
- mode++;
- idx++;
- continue;
- }
-
- pfd = &pfds [i - mode];
- if (pfd->revents == 0)
- continue;
-
- ret--;
- if (mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
- mono_array_setref (socks, idx++, obj);
- } else if (mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
- mono_array_setref (socks, idx++, obj);
- } else if ((pfd->revents & POLL_ERRORS) != 0) {
- mono_array_setref (socks, idx++, obj);
- }
+ set_socks_array_from_pollfds (sockets, i, pfds, &ret, &mode, socks, &idx);
}
- *sockets = socks;
+ MONO_HANDLE_ASSIGN (sockets, socks);
g_free (pfds);
}
-static MonoObject*
-int_to_object (MonoDomain *domain, int val, MonoError *error)
+static MonoObjectHandle
+int_to_object_handle (MonoDomain *domain, int val, MonoError *error)
{
- return mono_value_box_checked (domain, mono_get_int32_class (), &val, error);
+ return MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (domain, mono_get_int32_class (), &val, error));
}
void
-ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gint32 level, gint32 name, MonoObjectHandle obj_val, gint32 *werror, MonoError *error)
{
int system_level = 0;
int system_name = 0;
# endif
socklen_t credsize = sizeof (cred);
#endif
- MonoError error;
MonoDomain *domain = mono_domain_get ();
- MonoObject *obj;
MonoClass *obj_class;
MonoClassField *field;
+ error_init (error);
*werror = 0;
#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
return;
}
if (ret == -2) {
- *obj_val = int_to_object (domain, 0, &error);
- mono_error_set_pending_exception (&error);
+ MONO_HANDLE_ASSIGN (obj_val, int_to_object_handle (domain, 0, error));
return;
}
}
switch (name) {
- case SocketOptionName_Linger:
+ case SocketOptionName_Linger: {
/* build a System.Net.Sockets.LingerOption */
obj_class = mono_class_load_from_name (get_socket_assembly (),
"System.Net.Sockets",
"LingerOption");
- obj = mono_object_new_checked (domain, obj_class, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
+ MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, obj_class, error));
+ return_if_nok (error);
/* Locate and set the fields "bool enabled" and "int
* lingerTime"
*/
field = mono_class_get_field_from_name(obj_class, "enabled");
- *(guint8 *)(((char *)obj)+field->offset) = linger.l_onoff;
+ MONO_HANDLE_SET_FIELD_VAL (obj, guint8, field, linger.l_onoff);
field = mono_class_get_field_from_name(obj_class, "lingerTime");
- *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
+ MONO_HANDLE_SET_FIELD_VAL (obj, guint32, field, linger.l_linger);
+
+ MONO_HANDLE_ASSIGN (obj_val, obj);
break;
- case SocketOptionName_DontLinger:
+ }
+ case SocketOptionName_DontLinger: {
/* construct a bool int in val - true if linger is off */
- obj = int_to_object (domain, !linger.l_onoff, &error);
- mono_error_set_pending_exception (&error);
+ MonoObjectHandle obj = int_to_object_handle (domain, !linger.l_onoff, error);
+ return_if_nok (error);
+
+ MONO_HANDLE_ASSIGN (obj_val, obj);
break;
+ }
case SocketOptionName_SendTimeout:
- case SocketOptionName_ReceiveTimeout:
- obj = int_to_object (domain, time_ms, &error);
- mono_error_set_pending_exception (&error);
+ case SocketOptionName_ReceiveTimeout: {
+ MonoObjectHandle obj = int_to_object_handle (domain, time_ms, error);
+ return_if_nok (error);
+
+ MONO_HANDLE_ASSIGN (obj_val, obj);
break;
+ }
#ifdef SO_PEERCRED
case SocketOptionName_PeerCred: {
* possible
*/
static MonoImage *mono_posix_image = NULL;
- MonoPeerCredData *cred_data;
if (mono_posix_image == NULL) {
mono_posix_image = mono_image_loaded ("Mono.Posix");
obj_class = mono_class_load_from_name (mono_posix_image,
"Mono.Posix",
"PeerCredData");
- obj = mono_object_new_checked (domain, obj_class, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
- cred_data = (MonoPeerCredData *)obj;
- cred_data->pid = cred.pid;
- cred_data->uid = cred.uid;
- cred_data->gid = cred.gid;
+ MonoPeerCredDataHandle cred_data = MONO_HANDLE_NEW (MonoPeerCredData, mono_object_new_checked (domain, obj_class, error));
+ return_if_nok (error);
+
+ MONO_HANDLE_SETVAL (cred_data, pid, gint, cred.pid);
+ MONO_HANDLE_SETVAL (cred_data, uid, gint, cred.uid);
+ MONO_HANDLE_SETVAL (cred_data, gid, gint, cred.gid);
+
+ MONO_HANDLE_ASSIGN (obj_val, cred_data);
break;
}
#endif
- default:
+ default: {
#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse)
val = val ? 0 : 1;
#endif
- obj = int_to_object (domain, val, &error);
- mono_error_set_pending_exception (&error);
- }
+ MonoObjectHandle obj = int_to_object_handle (domain, val, error);
+ return_if_nok (error);
- *obj_val = obj;
+ MONO_HANDLE_ASSIGN (obj_val, obj);
+ }
+ }
}
void
-ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gint32 level, gint32 name, MonoArrayHandle byte_val, gint32 *werror, MonoError *error)
{
int system_level = 0;
int system_name = 0;
int ret;
- guchar *buf;
socklen_t valsize;
+ error_init (error);
*werror = 0;
ret = convert_sockopt_level_and_name((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level,
if (ret == -2)
return;
- valsize = mono_array_length (*byte_val);
- buf = mono_array_addr (*byte_val, guchar, 0);
+ valsize = mono_array_handle_length (byte_val);
+
+ uint32_t gchandle;
+ guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle);
MONO_ENTER_GC_SAFE;
MONO_EXIT_GC_SAFE;
+ mono_gchandle_free (gchandle);
+
if (ret == SOCKET_ERROR)
*werror = mono_w32socket_get_last_error ();
}
#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
static struct in_addr
-ipaddress_to_struct_in_addr (MonoObject *ipaddr)
+ipaddress_handle_to_struct_in_addr (MonoObjectHandle ipaddr)
{
struct in_addr inaddr;
MonoClassField *field;
- field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Address");
+ field = mono_class_get_field_from_name (mono_handle_class (ipaddr), "m_Address");
+ g_assert (field);
/* No idea why .net uses a 64bit type to hold a 32bit value...
*
* Internal value of IPAddess is in little-endian order
*/
- inaddr.s_addr = GUINT_FROM_LE ((guint32)*(guint64 *)(((char *)ipaddr) + field->offset));
+ inaddr.s_addr = GUINT_FROM_LE ((guint32)MONO_HANDLE_GET_FIELD_VAL (ipaddr, guint64, field));
return inaddr;
}
#ifdef HAVE_STRUCT_SOCKADDR_IN6
static struct in6_addr
-ipaddress_to_struct_in6_addr (MonoObject *ipaddr)
+ipaddress_handle_to_struct_in6_addr (MonoObjectHandle ipaddr)
{
struct in6_addr in6addr;
MonoClassField *field;
- MonoArray *data;
int i;
- field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Numbers");
+ field = mono_class_get_field_from_name (mono_handle_class (ipaddr), "m_Numbers");
g_assert (field);
- data = *(MonoArray **)(((char *)ipaddr) + field->offset);
+ MonoArrayHandle data = MONO_HANDLE_NEW_GET_FIELD (ipaddr, MonoArray, field);
for (i = 0; i < 8; i++) {
- const guint16 s = GUINT16_TO_BE (mono_array_get (data, guint16, i));
+ guint16 v;
+ MONO_HANDLE_ARRAY_GETVAL (v, data, guint16, i);
+ const guint16 s = GUINT16_TO_BE (v);
/* Solaris/MacOS have only the 8 bit version. */
#ifndef s6_addr16
#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
void
-ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock, gint32 level, gint32 name, MonoObjectHandle obj_val, MonoArrayHandle byte_val, gint32 int_val, gint32 *werror, MonoError *error)
{
struct linger linger;
int system_level = 0;
int sol_ip;
int sol_ipv6;
+ error_init (error);
*werror = 0;
sol_ipv6 = mono_networking_get_ipv6_protocol ();
return;
/* Only one of obj_val, byte_val or int_val has data */
- if (obj_val) {
+ if (!MONO_HANDLE_IS_NULL (obj_val)) {
+ MonoClass *obj_class = mono_handle_class (obj_val);
MonoClassField *field;
int valsize;
/* Dig out "bool enabled" and "int lingerTime"
* fields
*/
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "enabled");
- linger.l_onoff = *(guint8 *)(((char *)obj_val) + field->offset);
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "lingerTime");
- linger.l_linger = *(guint32 *)(((char *)obj_val) + field->offset);
+ field = mono_class_get_field_from_name (obj_class, "enabled");
+ linger.l_onoff = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint8, field);
+ field = mono_class_get_field_from_name (obj_class, "lingerTime");
+ linger.l_linger = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint32, field);
valsize = sizeof (linger);
ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, valsize);
case SocketOptionName_DropMembership:
#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
{
- MonoObject *address = NULL;
+ MonoObjectHandle address = MONO_HANDLE_NEW (MonoObject, NULL);
#ifdef HAVE_STRUCT_SOCKADDR_IN6
if (system_level == sol_ipv6) {
struct ipv6_mreq mreq6;
/*
* Get group address
*/
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Group");
+ field = mono_class_get_field_from_name (obj_class, "m_Group");
g_assert (field);
- address = *(MonoObject **)(((char *)obj_val) + field->offset);
+ MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field));
- if (address)
- mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
+ if (!MONO_HANDLE_IS_NULL (address))
+ mreq6.ipv6mr_multiaddr = ipaddress_handle_to_struct_in6_addr (address);
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Interface");
- mreq6.ipv6mr_interface = *(guint64 *)(((char *)obj_val) + field->offset);
+ field = mono_class_get_field_from_name (obj_class, "m_Interface");
+ mreq6.ipv6mr_interface = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint64, field);
#if defined(__APPLE__) || defined(__FreeBSD__)
/*
* members, so I have to dig the value out of
* those :-(
*/
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
- address = *(MonoObject **)(((char *)obj_val) + field->offset);
+ field = mono_class_get_field_from_name (obj_class, "group");
+ MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field));
/* address might not be defined and if so, set the address to ADDR_ANY.
*/
- if (address)
- mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
+ if (!MONO_HANDLE_IS_NULL (address))
+ mreq.imr_multiaddr = ipaddress_handle_to_struct_in_addr (address);
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "localAddress");
- address = *(MonoObject **)(((char *)obj_val) + field->offset);
+ field = mono_class_get_field_from_name (obj_class, "localAddress");
+ MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field));
#ifdef HAVE_STRUCT_IP_MREQN
- if (address)
- mreq.imr_address = ipaddress_to_struct_in_addr (address);
+ if (!MONO_HANDLE_IS_NULL (address))
+ mreq.imr_address = ipaddress_handle_to_struct_in_addr (address);
- field = mono_class_get_field_from_name (obj_val->vtable->klass, "ifIndex");
- mreq.imr_ifindex = *(gint32 *)(((char *)obj_val) + field->offset);
+ field = mono_class_get_field_from_name (obj_class, "ifIndex");
+ mreq.imr_ifindex = MONO_HANDLE_GET_FIELD_VAL (obj_val, gint32, field);
#else
- if (address)
- mreq.imr_interface = ipaddress_to_struct_in_addr (address);
+ if (!MONO_HANDLE_IS_NULL (address))
+ mreq.imr_interface = ipaddress_handle_to_struct_in_addr (address);
#endif /* HAVE_STRUCT_IP_MREQN */
ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq, sizeof (mreq));
*werror = WSAEINVAL;
return;
}
- } else if (byte_val!=NULL) {
- int valsize = mono_array_length (byte_val);
- guchar *buf = mono_array_addr (byte_val, guchar, 0);
+ } else if (!MONO_HANDLE_IS_NULL (byte_val)) {
+ int valsize = mono_array_handle_length (byte_val);
+ uint32_t gchandle;
+ guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle);
switch(name) {
case SocketOptionName_DontLinger:
ret = mono_w32socket_setsockopt (sock, system_level, system_name, buf, valsize);
break;
}
+ mono_gchandle_free (gchandle);
} else {
/* ReceiveTimeout/SendTimeout get here */
switch (name) {
}
void
-ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *werror, MonoError *error)
{
int ret;
gboolean interrupted;
+ error_init (error);
*werror = 0;
mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
}
gint
-ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *werror)
+ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, MonoArrayHandle input, MonoArrayHandle output, gint32 *werror, MonoError *error)
{
glong output_bytes = 0;
gchar *i_buffer, *o_buffer;
gint i_len, o_len;
+ uint32_t i_gchandle, o_gchandle;
gint ret;
+ error_init (error);
*werror = 0;
if ((guint32)code == FIONBIO)
/* Invalid command. Must use Socket.Blocking */
return -1;
- if (input == NULL) {
+ if (MONO_HANDLE_IS_NULL (input)) {
i_buffer = NULL;
i_len = 0;
+ i_gchandle = 0;
} else {
- i_buffer = mono_array_addr (input, gchar, 0);
- i_len = mono_array_length (input);
+ i_len = mono_array_handle_length (input);
+ i_buffer = MONO_ARRAY_HANDLE_PIN (input, gchar, 0, &i_gchandle);
}
- if (output == NULL) {
+ if (MONO_HANDLE_IS_NULL (output)) {
o_buffer = NULL;
o_len = 0;
+ o_gchandle = 0;
} else {
- o_buffer = mono_array_addr (output, gchar, 0);
- o_len = mono_array_length (output);
+ o_len = mono_array_handle_length (output);
+ o_buffer = MONO_ARRAY_HANDLE_PIN (output, gchar, 0, &o_gchandle);
}
MONO_ENTER_GC_SAFE;
MONO_EXIT_GC_SAFE;
+ if (i_gchandle)
+ mono_gchandle_free (i_gchandle);
+ if (o_gchandle)
+ mono_gchandle_free (o_gchandle);
+
if (ret == SOCKET_ERROR) {
*werror = mono_w32socket_get_last_error ();
return -1;
return (gint)output_bytes;
}
-static gboolean
-addrinfo_to_IPHostEntry (MonoAddressInfo *info, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gboolean add_local_ips, MonoError *error)
+static gboolean
+addrinfo_add_string (MonoDomain *domain, const char *s, MonoArrayHandle arr, int index, MonoError *error)
{
- gint32 count, i;
- MonoAddressEntry *ai = NULL;
+ HANDLE_FUNCTION_ENTER ();
+ error_init (error);
+ MonoStringHandle str = mono_string_new_handle (domain, s, error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_HANDLE_ARRAY_SETREF (arr, index, str);
+leave:
+ HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
+
+}
+
+static int
+addrinfo_add_local_ips (MonoDomain *domain, MonoArrayHandleOut h_addr_list, MonoError *error)
+{
+ HANDLE_FUNCTION_ENTER ();
struct in_addr *local_in = NULL;
int nlocal_in = 0;
struct in6_addr *local_in6 = NULL;
int nlocal_in6 = 0;
- int addr_index;
- MonoDomain *domain = mono_domain_get ();
+ int addr_index = 0;
error_init (error);
- addr_index = 0;
- *h_aliases = mono_array_new_checked (domain, mono_get_string_class (), 0, error);
- return_val_if_nok (error, FALSE);
- if (add_local_ips) {
- local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in);
- local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6);
- if (nlocal_in || nlocal_in6) {
- char addr [INET6_ADDRSTRLEN];
- *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), nlocal_in + nlocal_in6, error);
- if (!is_ok (error))
- goto leave;
+ local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in);
+ local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6);
+ if (nlocal_in || nlocal_in6) {
+ char addr [INET6_ADDRSTRLEN];
+ MONO_HANDLE_ASSIGN (h_addr_list, mono_array_new_handle (domain, mono_get_string_class (), nlocal_in + nlocal_in6, error));
+ if (!is_ok (error))
+ goto leave;
- if (nlocal_in) {
- MonoString *addr_string;
- int i;
-
- for (i = 0; i < nlocal_in; i++) {
- MonoAddress maddr;
- mono_address_init (&maddr, AF_INET, &local_in [i]);
- if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
- addr_string = mono_string_new_checked (domain, addr, error);
- if (!is_ok (error))
- goto leave;
- mono_array_setref (*h_addr_list, addr_index, addr_string);
- addr_index++;
- }
+ if (nlocal_in) {
+ int i;
+
+ for (i = 0; i < nlocal_in; i++) {
+ MonoAddress maddr;
+ mono_address_init (&maddr, AF_INET, &local_in [i]);
+ if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
+ if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error))
+ goto leave;
+ addr_index++;
}
}
+ }
#ifdef HAVE_STRUCT_SOCKADDR_IN6
- if (nlocal_in6) {
- MonoString *addr_string;
- int i;
-
- for (i = 0; i < nlocal_in6; i++) {
- MonoAddress maddr;
- mono_address_init (&maddr, AF_INET6, &local_in6 [i]);
- if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
- addr_string = mono_string_new_checked (domain, addr, error);
- if (!is_ok (error))
- goto leave;
- mono_array_setref (*h_addr_list, addr_index, addr_string);
- addr_index++;
- }
+ if (nlocal_in6) {
+ int i;
+
+ for (i = 0; i < nlocal_in6; i++) {
+ MonoAddress maddr;
+ mono_address_init (&maddr, AF_INET6, &local_in6 [i]);
+ if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
+ if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error))
+ goto leave;
+ addr_index++;
}
}
-#endif
- leave:
- g_free (local_in);
- g_free (local_in6);
- if (info)
- mono_free_address_info (info);
- return is_ok (error);;
}
+#endif
+ }
- g_free (local_in);
- g_free (local_in6);
+leave:
+ g_free (local_in);
+ g_free (local_in6);
+ HANDLE_FUNCTION_RETURN_VAL (addr_index);
+}
+
+static gboolean
+addrinfo_to_IPHostEntry_handles (MonoAddressInfo *info, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gboolean add_local_ips, MonoError *error)
+{
+ HANDLE_FUNCTION_ENTER ();
+ MonoAddressEntry *ai = NULL;
+ MonoDomain *domain = mono_domain_get ();
+
+ error_init (error);
+ MONO_HANDLE_ASSIGN (h_aliases, mono_array_new_handle (domain, mono_get_string_class (), 0, error));
+ if (!is_ok (error))
+ goto leave;
+ if (add_local_ips) {
+ int addr_index = addrinfo_add_local_ips (domain, h_addr_list, error);
+ if (!is_ok (error))
+ goto leave;
+ if (addr_index > 0)
+ goto leave;
}
- for (count = 0, ai = info->entries; ai != NULL; ai = ai->next) {
+ gint32 count = 0;
+ for (ai = info->entries; ai != NULL; ai = ai->next) {
if (ai->family != AF_INET && ai->family != AF_INET6)
continue;
count++;
}
- *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), count, error);
+ int addr_index = 0;
+ MONO_HANDLE_ASSIGN (h_addr_list, mono_array_new_handle (domain, mono_get_string_class (), count, error));
if (!is_ok (error))
- goto leave2;
+ goto leave;
- for (ai = info->entries, i = 0; ai != NULL; ai = ai->next) {
+ gboolean name_assigned = FALSE;
+ for (ai = info->entries; ai != NULL; ai = ai->next) {
MonoAddress maddr;
- MonoString *addr_string;
char buffer [INET6_ADDRSTRLEN]; /* Max. size for IPv6 */
if ((ai->family != PF_INET) && (ai->family != PF_INET6))
continue;
mono_address_init (&maddr, ai->family, &ai->address);
+ const char *addr = NULL;
if (mono_networking_addr_to_str (&maddr, buffer, sizeof (buffer)))
- addr_string = mono_string_new_checked (domain, buffer, error);
+ addr = buffer;
else
- addr_string = mono_string_new_checked (domain, "", error);
- if (!is_ok (error))
- goto leave2;
-
- mono_array_setref (*h_addr_list, addr_index, addr_string);
-
- if (!i) {
- i++;
- if (ai->canonical_name != NULL) {
- *h_name = mono_string_new_checked (domain, ai->canonical_name, error);
- } else {
- *h_name = mono_string_new_checked (domain, buffer, error);
- }
+ addr = "";
+ if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error))
+ goto leave;
+
+ if (!name_assigned) {
+ name_assigned = TRUE;
+ const char *name = ai->canonical_name != NULL ? ai->canonical_name : buffer;
+ MONO_HANDLE_ASSIGN (h_name, mono_string_new_handle (domain, name, error));
if (!is_ok (error))
- goto leave2;
+ goto leave;
}
addr_index++;
}
-leave2:
+leave:
if (info)
mono_free_address_info (info);
- return is_ok (error);
+ HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
}
MonoBoolean
-ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
+ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error)
{
- MonoError error;
gboolean add_local_ips = FALSE, add_info_ok = TRUE;
gchar this_hostname [256];
MonoAddressInfo *info = NULL;
- char *hostname = mono_string_to_utf8_checked (host, &error);
- if (mono_error_set_pending_exception (&error))
- return FALSE;
+ error_init (error);
+
+ char *hostname = mono_string_handle_to_utf8 (host, error);
+ return_val_if_nok (error, FALSE);
if (*hostname == '\0') {
add_local_ips = TRUE;
- *h_name = host;
+ MONO_HANDLE_ASSIGN (h_name, host);
}
if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) {
if (!strcmp (hostname, this_hostname)) {
add_local_ips = TRUE;
- *h_name = host;
+ MONO_HANDLE_ASSIGN (h_name, host);
}
}
g_free(hostname);
if (add_info_ok) {
- MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, add_local_ips, &error);
- mono_error_set_pending_exception (&error);
+ MonoBoolean result = addrinfo_to_IPHostEntry_handles (info, h_name, h_aliases, h_addr_list, add_local_ips, error);
return result;
}
return FALSE;
}
MonoBoolean
-ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
+ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error)
{
char *address;
struct sockaddr_in saddr;
struct sockaddr_in6 saddr6;
#endif
MonoAddressInfo *info = NULL;
- MonoError error;
gint32 family;
gchar hostname [NI_MAXHOST] = { 0 };
gboolean ret;
- address = mono_string_to_utf8_checked (addr, &error);
- if (mono_error_set_pending_exception (&error))
- return FALSE;
+ error_init (error);
+
+ address = mono_string_handle_to_utf8 (addr, error);
+ return_val_if_nok (error, FALSE);
if (inet_pton (AF_INET, address, &saddr.sin_addr ) == 1) {
family = AF_INET;
if (mono_get_address_info (hostname, 0, hint | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info) != 0)
return FALSE;
- MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, FALSE, &error);
- mono_error_set_pending_exception (&error);
+ MonoBoolean result = addrinfo_to_IPHostEntry_handles (info, h_name, h_aliases, h_addr_list, FALSE, error);
return result;
}
MonoBoolean
-ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name)
+ves_icall_System_Net_Dns_GetHostName_internal (MonoStringHandleOut h_name, MonoError *error)
{
- MonoError error;
gchar hostname [NI_MAXHOST] = { 0 };
int ret;
+ error_init (error);
+ MONO_ENTER_GC_SAFE;
ret = gethostname (hostname, sizeof (hostname));
+ MONO_EXIT_GC_SAFE;
if (ret == -1)
return FALSE;
- *h_name = mono_string_new_checked (mono_domain_get (), hostname, &error);
- mono_error_set_pending_exception (&error);
-
+ MONO_HANDLE_ASSIGN (h_name, mono_string_new_handle (mono_domain_get (), hostname, error));
return TRUE;
}
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
gboolean
-ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags, gint32 *werror, gboolean blocking)
+ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHandle filename, MonoArrayHandle pre_buffer, MonoArrayHandle post_buffer, gint flags, gint32 *werror, gboolean blocking, MonoError *error)
{
HANDLE file;
gboolean ret;
gboolean interrupted;
TRANSMIT_FILE_BUFFERS buffers;
+ uint32_t pre_buffer_gchandle = 0;
+ uint32_t post_buffer_gchandle = 0;
+ error_init (error);
*werror = 0;
- if (filename == NULL)
+ if (MONO_HANDLE_IS_NULL (filename))
return FALSE;
/* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
- file = mono_w32file_create (mono_string_chars (filename), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0);
+ uint32_t filename_gchandle;
+ gunichar2 *filename_chars = mono_string_handle_pin_chars (filename, &filename_gchandle);
+ file = mono_w32file_create (filename_chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0);
+ mono_gchandle_free (filename_gchandle);
if (file == INVALID_HANDLE_VALUE) {
*werror = mono_w32error_get_last ();
return FALSE;
}
- memset (&buffers, 0, sizeof (buffers));
- if (pre_buffer != NULL) {
- buffers.Head = mono_array_addr (pre_buffer, guchar, 0);
- buffers.HeadLength = mono_array_length (pre_buffer);
- }
- if (post_buffer != NULL) {
- buffers.Tail = mono_array_addr (post_buffer, guchar, 0);
- buffers.TailLength = mono_array_length (post_buffer);
- }
-
mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
if (interrupted) {
mono_w32file_close (file);
return FALSE;
}
+
+ memset (&buffers, 0, sizeof (buffers));
+ if (!MONO_HANDLE_IS_NULL (pre_buffer)) {
+ buffers.Head = MONO_ARRAY_HANDLE_PIN (pre_buffer, guchar, 0, &pre_buffer_gchandle);
+ buffers.HeadLength = mono_array_handle_length (pre_buffer);
+ }
+ if (!MONO_HANDLE_IS_NULL (post_buffer)) {
+ buffers.Tail = MONO_ARRAY_HANDLE_PIN (post_buffer, guchar, 0, &post_buffer_gchandle);
+ buffers.TailLength = mono_array_handle_length (post_buffer);
+ }
+
MONO_ENTER_GC_SAFE;
ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking);
MONO_EXIT_GC_SAFE;
+ if (pre_buffer_gchandle)
+ mono_gchandle_free (pre_buffer_gchandle);
+ if (post_buffer_gchandle)
+ mono_gchandle_free (post_buffer_gchandle);
+
if (!ret)
*werror = mono_w32socket_get_last_error ();
}
void
-icall_cancel_blocking_socket_operation (MonoThread *thread)
+icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread, MonoError *error)
{
- MonoInternalThread *internal;
-
- internal = thread->internal_thread;
- g_assert (internal);
+ error_init (error);
+ MonoInternalThreadHandle internal = MONO_HANDLE_NEW_GET (MonoInternalThread, thread, internal_thread);
+ g_assert (!MONO_HANDLE_IS_NULL (internal));
- mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid));
+ guint64 tid = mono_internal_thread_handle_ptr (internal)->tid;
+ mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (tid));
}
#endif /* #ifndef DISABLE_SOCKETS */
gint gid;
} MonoPeerCredData;
+/* Safely access Mono.Posix.PeerCredData from native code */
+TYPED_HANDLE_DECL (MonoPeerCredData);
+
gpointer
-ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto,
- gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObjectHandle this_obj, gint32 family, gint32 type,
+ gint32 proto, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror, MonoError *error);
gint32
ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void);
gint32
-ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *werror, MonoError *error);
gpointer
-ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror, gboolean blocking, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Listen_internal (gsize sock, guint32 backlog, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Listen_internal (gsize sock, guint32 backlog, gint32 *werror, MonoError *error);
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *error);
+MonoObjectHandle
+ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *werror, MonoError *error);
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *error);
+MonoObjectHandle
+ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObject *sockaddr, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObject *sockaddr, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, gboolean blocking, MonoError *error);
gint32
-ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count,
- gint32 flags, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count,
+ gint32 flags, gint32 *werror, gboolean blocking, MonoError *error);
gint32
-ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *error,
- gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArrayHandle buffers, gint32 flags,
+ gint32 *werror, gboolean blocking, MonoError *error);
+
+/* gint32 */
+/* ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, */
+/* gint32 flags, MonoObject **sockaddr, gint32 *werror, gboolean blocking); */
gint32
-ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count,
- gint32 flags, MonoObject **sockaddr, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count,
+ gint32 flags, MonoObjectHandle sockaddr, gint32 *werror, gboolean blocking, MonoError *error);
+
gint32
-ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count,
- gint32 flags, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count,
+ gint32 flags, gint32 *werror, gboolean blocking, MonoError *error);
gint32
-ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *error,
- gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArrayHandle buffers, gint32 flags,
+ gint32 *werror, gboolean blocking, MonoError *error);
gint32
-ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count,
- gint32 flags, MonoObject *sockaddr, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count,
+ gint32 flags, MonoObjectHandle sockaddr, gint32 *werror,
+ gboolean blocking, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArrayHandle sockets, gint32 timeout, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *werror, MonoError *error);
void
ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gint32 level, gint32 name,
- MonoObject **obj_val, gint32 *error);
+ MonoObjectHandle obj_val, gint32 *werror,
+ MonoError *error);
void
ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gint32 level, gint32 name,
- MonoArray **byte_val, gint32 *error);
+ MonoArrayHandle byte_val, gint32 *werror,
+ MonoError *error);
void
ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock, gint32 level, gint32 name,
- MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error);
+ MonoObjectHandle obj_val, MonoArrayHandle byte_val,
+ gint32 int_val, gint32 *werror, MonoError *error);
int
-ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, MonoArray *input, MonoArray *output,
- gint32 *error);
+ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code,
+ MonoArrayHandle input, MonoArrayHandle output,
+ gint32 *werror, MonoError *error);
MonoBoolean
-ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases,
- MonoArray **h_addr_list, gint32 hint);
+ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host, MonoStringHandleOut h_name,
+ MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list,
+ gint32 hint, MonoError *error);
MonoBoolean
-ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases,
- MonoArray **h_addr_list, gint32 hint);
+ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStringHandleOut h_name,
+ MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list,
+ gint32 hint, MonoError *error);
MonoBoolean
-ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name);
+ves_icall_System_Net_Dns_GetHostName_internal (MonoStringHandleOut h_name, MonoError *error);
MonoBoolean
-ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint timeout, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint timeout, gint32 *werror, MonoError *error);
void
-ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *error);
+ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror, MonoError *error);
gboolean
-ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoString *filename, MonoArray *pre_buffer,
- MonoArray *post_buffer, gint flags, gint32 *error, gboolean blocking);
+ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHandle filename,
+ MonoArrayHandle pre_buffer, MonoArrayHandle post_buffer,
+ gint flags, gint32 *werror, gboolean blocking, MonoError *error);
void
-icall_cancel_blocking_socket_operation (MonoThread *thread);
+icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread, MonoError *error);
gboolean
-ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto);
+ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error);
void
mono_network_init(void);
MemoryIntrinsics.il \
mixed.cs
-if NACL_CODEGEN
-test_sources += nacl.cs
-endif
-
regtests_UNIVERSAL = \
basic.exe \
basic-float.exe \
unaligned.exe \
basic-vectors.exe
-if NACL_CODEGEN
-regtests_UNIVERSAL += nacl.exe
-endif
-
regtests_DISABLED =
if FULL_AOT_TESTS
MemoryIntrinsics.dll: MemoryIntrinsics.il
$(ILASM) -dll -output=$@ $<
-if NACL_CODEGEN
-GENMDESC_OPTS=--nacl
-else !NACL_CODEGEN
GENMDESC_OPTS=
-endif !NACL_CODEGEN
# we don't always use the perl impl because it's an additional
# build dependency for the poor windows users
if CROSS_COMPILING
GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS)
else !CROSS_COMPILING
-if NACL_CODEGEN
-GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS)
-else
GENMDESC_PRG=./genmdesc $(GENMDESC_OPTS)
-endif
endif !CROSS_COMPILING
cpu-x86.h: cpu-x86.md genmdesc$(EXEEXT)
#include <mono/utils/mono-rand.h>
#include <mono/utils/json.h>
#include <mono/utils/mono-threads-coop.h>
-#include <mono/profiler/mono-profiler-aot.h>
+#include <mono/profiler/aot.h>
#include <mono/utils/w32api.h>
#include "aot-compiler.h"
#define TARGET_WIN32_MSVC
#endif
-#if defined(__linux__) || defined(__native_client_codegen__)
+#if defined(__linux__)
#define RODATA_SECT ".rodata"
#elif defined(TARGET_MACH)
#define RODATA_SECT ".section __TEXT, __const"
#ifdef TARGET_X86
#ifdef TARGET_WIN32
#define AOT_TARGET_STR "X86 (WIN32)"
-#elif defined(__native_client_codegen__)
-#define AOT_TARGET_STR "X86 (native client codegen)"
#else
-#define AOT_TARGET_STR "X86 (!native client codegen)"
+#define AOT_TARGET_STR "X86"
#endif
#endif
static
gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
{
- return opts->mode == MONO_AOT_MODE_FULL;
+ return opts->mode == MONO_AOT_MODE_FULL || opts->mode == MONO_AOT_MODE_INTERP;
+}
+
+static
+gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
+{
+ return opts->mode == MONO_AOT_MODE_INTERP;
}
static
#endif /* #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES */
+ if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
+ mono_arch_get_enter_icall_trampoline (&info);
+ emit_trampoline (acfg, acfg->got_offset, info);
+ }
+
/* Emit trampolines which are numerous */
/*
opts->mode = MONO_AOT_MODE_FULL;
} else if (str_begins_with (arg, "hybrid")) {
opts->mode = MONO_AOT_MODE_HYBRID;
+ } else if (str_begins_with (arg, "interp")) {
+ opts->mode = MONO_AOT_MODE_INTERP;
} else if (str_begins_with (arg, "threads=")) {
opts->nthreads = atoi (arg + strlen ("threads="));
} else if (str_begins_with (arg, "static")) {
{
int status = 0;
-#if defined(HOST_WIN32) && defined(HAVE_SYSTEM)
+#if defined(HOST_WIN32)
// We need an extra set of quotes around the whole command to properly handle commands
// with spaces since internally the command is called through "cmd /c.
char * quoted_command = g_strdup_printf ("\"%s\"", command);
#define AS_OPTIONS "-a64 -mppc64"
#elif defined(sparc) && SIZEOF_VOID_P == 8
#define AS_OPTIONS "-xarch=v9"
-#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH)
#define AS_OPTIONS "-arch i386"
#else
#define AS_OPTIONS ""
#endif
-#ifdef __native_client_codegen__
-#if defined(TARGET_AMD64)
-#define AS_NAME "nacl64-as"
-#else
-#define AS_NAME "nacl-as"
-#endif
-#elif defined(TARGET_OSX)
+#if defined(TARGET_OSX)
#define AS_NAME "clang"
#elif defined(TARGET_WIN32_MSVC)
#define AS_NAME "clang.exe"
#elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
#define LD_NAME "gcc"
#define LD_OPTIONS "-shared"
-#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH)
#define LD_NAME "clang"
#define LD_OPTIONS "-m32 -dynamiclib"
#elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
}
}
- {
+ if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
int method_index;
for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
mono_set_partial_sharing_supported (TRUE);
- res = collect_methods (acfg);
- if (!res)
- return 1;
+ if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
+ res = collect_methods (acfg);
+
+ if (!res)
+ return 1;
+ }
{
GList *l;
}
#endif
+ if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
+ MonoMethod *wrapper;
+ MonoMethodSignature *sig;
+
+ /* object object:interp_in_static (object,intptr,intptr,intptr) */
+ sig = mono_create_icall_signature ("object object ptr ptr ptr");
+ wrapper = mini_get_interp_in_wrapper (sig);
+ add_method (acfg, wrapper);
+
+ /* int object:interp_in_static (intptr,int,intptr) */
+ sig = mono_create_icall_signature ("int32 ptr int32 ptr");
+ wrapper = mini_get_interp_in_wrapper (sig);
+ add_method (acfg, wrapper);
+
+ /* void object:interp_in_static (object,intptr,intptr,intptr) */
+ sig = mono_create_icall_signature ("void object ptr ptr ptr");
+ wrapper = mini_get_interp_in_wrapper (sig);
+ add_method (acfg, wrapper);
+ }
+
TV_GETTIME (atv);
compile_methods (acfg);
ref->method = mono_marshal_get_gsharedvt_in_wrapper ();
} else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
ref->method = mono_marshal_get_gsharedvt_out_wrapper ();
+ } else if (subtype == WRAPPER_SUBTYPE_INTERP_IN) {
+ ref->method = mini_get_interp_in_wrapper (target->signature);
} else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
MonoMethodSignature *sig = decode_signature (module, p, &p);
if (!sig)
}
}
if (!sofile) {
- if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows) {
+ if (mono_aot_only && !mono_use_interpreter && assembly->image->tables [MONO_TABLE_METHOD].rows) {
aot_name = g_strdup_printf ("%s%s", assembly->image->name, MONO_SOLIB_EXT);
g_error ("Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
g_free (aot_name);
}
if (!usable) {
- if (mono_aot_only) {
+ if (mono_aot_only && !mono_use_interpreter) {
g_error ("Failed to load AOT module '%s' while running in aot-only mode: %s.\n", found_aot_name, msg);
} else {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable: %s.", found_aot_name, msg);
* non-lazily, since we can't handle out-of-date errors later.
* The cached class info also depends on the exact assemblies.
*/
-#if defined(__native_client__)
- /* TODO: Don't 'load_image' on mscorlib due to a */
- /* recursive loading problem. This should be */
- /* removed if mscorlib is loaded from disk. */
- if (strncmp(assembly->aname.name, "mscorlib", 8)) {
- do_load_image = TRUE;
- } else {
- do_load_image = FALSE;
- }
-#endif
if (do_load_image) {
for (i = 0; i < amodule->image_table_len; ++i) {
MonoError error;
mono_os_mutex_init_recursive (&aot_page_mutex);
aot_modules = g_hash_table_new (NULL, NULL);
-#ifndef __native_client__
mono_install_assembly_load_hook (load_aot_module, NULL);
-#endif
mono_counters_register ("Async JIT info size", MONO_COUNTER_INT|MONO_COUNTER_JIT, &async_jit_info_size);
char *lastaot = g_getenv ("MONO_LASTAOT");
}
static void
-replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) {
+replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl)
+{
MonoInst *ins;
-
-#if defined(__native_client_codegen__)
- /* Need to maintain this flag for the new block because */
- /* we can't jump indirectly to a non-aligned block. */
- if (orig->flags & BB_INDIRECT_JUMP_TARGET)
- {
- repl->flags |= BB_INDIRECT_JUMP_TARGET;
- }
-#endif
for (ins = bb->code; ins != NULL; ins = ins->next) {
switch (ins->opcode) {
args [i] = arg_buf [i];
}
} else {
- arg_buf [i] = (guint8 *)g_alloca (mono_class_instance_size (mono_class_from_mono_type (sig->params [i])));
+ MonoClass *arg_class = mono_class_from_mono_type (sig->params [i]);
+ arg_buf [i] = (guint8 *)g_alloca (mono_class_instance_size (arg_class));
err = decode_value (sig->params [i], domain, arg_buf [i], p, &p, end);
if (err != ERR_NONE)
break;
- args [i] = arg_buf [i];
+ if (mono_class_is_nullable (arg_class)) {
+ args [i] = mono_nullable_box (arg_buf [i], arg_class, &error);
+ mono_error_assert_ok (&error);
+ } else {
+ args [i] = arg_buf [i];
+ }
}
}
#endif
-#ifdef __native_client__
-extern char *nacl_mono_path;
-#endif
-
#define DEFAULT_OPTIMIZATIONS ( \
MONO_OPT_PEEPHOLE | \
MONO_OPT_CFOLD | \
#ifdef HOST_WIN32
int mixed_mode = FALSE;
#endif
-#ifdef __native_client__
- gboolean nacl_null_checks_off = FALSE;
-#endif
#ifdef MOONLIGHT
#ifndef HOST_WIN32
#else
fprintf (stderr, "Mono Warning: --interp= not enabled in this runtime.\n");
#endif
-
-#ifdef __native_client__
- } else if (strcmp (argv [i], "--nacl-mono-path") == 0){
- nacl_mono_path = g_strdup(argv[++i]);
- } else if (strcmp (argv [i], "--nacl-null-checks-off") == 0){
- nacl_null_checks_off = TRUE;
-#endif
} else if (strncmp (argv [i], "--assembly-loader=", strlen("--assembly-loader=")) == 0) {
gchar *arg = argv [i] + strlen ("--assembly-loader=");
if (strcmp (arg, "strict") == 0)
}
}
-#ifdef __native_client_codegen__
- if (!nacl_null_checks_off) {
- MonoDebugOptions *opt = mini_get_debug_options ();
- opt->explicit_null_checks = TRUE;
- }
-#endif
-
#if defined(DISABLE_HW_TRAPS) || defined(MONO_ARCH_DISABLE_HW_TRAPS)
// Signal handlers not available
{
mono_set_generic_sharing_vt_supported (TRUE);
mono_set_partial_sharing_supported (TRUE);
}
+ if (mono_aot_mode == MONO_AOT_MODE_INTERP) {
+ mono_aot_only = TRUE;
+ mono_use_interpreter = TRUE;
+ }
}
/**
return 0;
}
- [Category ("NaClDisable")]
public static int test_0_div_zero () {
int d = 1;
int q = 0;
return 0;
}
- [Category ("NaClDisable")]
public static int test_0_long_div_zero () {
long d = 1;
long q = 0;
#include <string.h>
#include <mono/metadata/opcodes.h>
-#if defined(__native_client__) || defined(__native_client_codegen__)
-volatile int __nacl_thread_suspension_needed = 0;
-void __nacl_suspend_thread_if_needed() {}
-#endif
-
#define MINI_OP(a,b,dest,src1,src2) b,
#define MINI_OP3(a,b,dest,src1,src2,src3) b,
/* keep in sync with the enum in mini.h */
void
mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
{
-#if defined(__native_client__)
- return;
-#endif
#ifndef DISABLE_LOGGING
GHashTable *offset_to_bb_hash = NULL;
int i, cindex, bb_num;
* TARGET_ASM_GAS == GNU assembler
*/
#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_ASM_GAS)
-#if defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#if defined(TARGET_MACH)
#define TARGET_ASM_APPLE
#else
#define TARGET_ASM_GAS
while (new_size <= new_offset)
new_size *= 2;
data = (guint8 *)g_malloc0 (new_size);
-#ifdef __native_client_codegen__
- /* for Native Client, fill empty space with HLT instruction */
- /* instead of 00. */
- memset(data, 0xf4, new_size);
-#endif
memcpy (data, section->data, section->data_len);
g_free (section->data);
section->data = data;
MonoType *rtype;
MonoType **param_types;
MonoJitInfo *jinfo;
+ MonoDomain *domain;
} RuntimeMethod;
struct _MonoInvocation {
};
typedef struct {
- MonoDomain *domain;
MonoDomain *original_domain;
MonoInvocation *base_frame;
MonoInvocation *current_frame;
rtm = mono_domain_alloc0 (domain, sizeof (RuntimeMethod));
rtm->method = method;
+ rtm->domain = domain;
rtm->param_count = sig->param_count;
rtm->hasthis = sig->hasthis;
rtm->rtype = mini_get_underlying_type (sig->ret);
}
static inline RuntimeMethod*
-get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObject *obj)
+get_virtual_method (RuntimeMethod *runtime_method, MonoObject *obj)
{
MonoMethod *m = runtime_method->method;
+ MonoDomain *domain = runtime_method->domain;
+ RuntimeMethod *ret = NULL;
MonoError error;
+#ifndef DISABLE_REMOTING
+ if (mono_object_is_transparent_proxy (obj)) {
+ ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
+ mono_error_assert_ok (&error);
+ return ret;
+ }
+#endif
+
if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
- RuntimeMethod *ret = NULL;
- if (mono_object_is_transparent_proxy (obj)) {
- ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- } else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
+ if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
ret = mono_interp_get_runtime_method (domain, mono_marshal_get_synchronized_wrapper (m), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
} else {
case MONO_TYPE_U4:
result->data.i = *(guint32*)data;
return;
- case MONO_TYPE_R4:
- result->data.f = *(float*)data;
+ case MONO_TYPE_R4: {
+ float tmp;
+ /* memmove handles unaligned case */
+ memmove (&tmp, data, sizeof (float));
+ result->data.f = tmp;
return;
+ }
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- result->data.l = *(gint64*)data;
+ memmove (&result->data.l, data, sizeof (gint64));
return;
case MONO_TYPE_R8:
- result->data.f = *(double*)data;
+ memmove (&result->data.f, data, sizeof (double));
return;
case MONO_TYPE_STRING:
case MONO_TYPE_SZARRAY:
{
MonoError error;
char *stack_trace = dump_frame (frame);
- MonoDomain *domain = mono_domain_get();
+ MonoDomain *domain = frame->runtime_method->domain;
(exception)->stack_trace = mono_string_new_checked (domain, stack_trace, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
(exception)->trace_ips = get_trace_ips (domain, frame);
g_assert (!frame->runtime_method);
if (!mono_interp_enter_icall_trampoline) {
- MonoTrampInfo *info;
- mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
- // TODO:
- // mono_tramp_info_register (info, NULL);
+ if (mono_aot_only) {
+ mono_interp_enter_icall_trampoline = mono_aot_get_trampoline ("enter_icall_trampoline");
+ } else {
+ MonoTrampInfo *info;
+ mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
+ // TODO:
+ // mono_tramp_info_register (info, NULL);
+ }
}
InterpMethodArguments *margs = build_args_from_sig (sig, frame);
interp_pop_lmf (&ext);
context->managed_code = 1;
- /* domain can only be changed by native code */
- context->domain = mono_domain_get ();
if (*mono_thread_interruption_request_flag ()) {
MonoException *exc = mono_thread_interruption_checkpoint ();
if (setjmp(env)) {
if (context != &context_struct) {
- context->domain = mono_domain_get ();
context->current_frame = old_frame;
context->managed_code = 0;
} else
else
old_frame = context->current_frame;
- context->domain = mono_domain_get ();
+ MonoDomain *domain = mono_domain_get ();
switch (sig->ret->type) {
case MONO_TYPE_VOID:
isobject = 1;
break;
case MONO_TYPE_VALUETYPE:
- retval = mono_object_new_checked (context->domain, klass, error);
+ retval = mono_object_new_checked (domain, klass, error);
ret = mono_object_unbox (retval);
if (!sig->ret->data.klass->enumtype)
result.data.vt = ret;
break;
case MONO_TYPE_GENERICINST:
if (!MONO_TYPE_IS_REFERENCE (sig->ret)) {
- retval = mono_object_new_checked (context->domain, klass, error);
+ retval = mono_object_new_checked (domain, klass, error);
ret = mono_object_unbox (retval);
if (!sig->ret->data.klass->enumtype)
result.data.vt = ret;
break;
case MONO_TYPE_PTR:
- retval = mono_object_new_checked (context->domain, mono_defaults.int_class, error);
+ retval = mono_object_new_checked (domain, mono_defaults.int_class, error);
ret = mono_object_unbox (retval);
break;
default:
- retval = mono_object_new_checked (context->domain, klass, error);
+ retval = mono_object_new_checked (domain, klass, error);
ret = mono_object_unbox (retval);
break;
}
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
- INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
+ INIT_FRAME (&frame,context->current_frame,args,&result,domain,method,error);
if (exc)
frame.invoke_trap = 1;
context->managed_code = 1;
} else {
old_frame = context->current_frame;
}
- context->domain = mono_domain_get ();
args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
if (sig->hasthis)
return sp;
}
+static stackval *
+do_jit_call (stackval *sp, unsigned char *vt_sp, ThreadContext *context, MonoInvocation *frame, RuntimeMethod *rmethod)
+{
+ MonoMethodSignature *sig;
+ MonoFtnDesc ftndesc;
+ guint8 res_buf [256];
+ MonoType *type;
+ MonoLMFExt ext;
+
+ //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
+
+ /*
+ * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
+ * by ref and return a return value using an explicit return value argument.
+ */
+ if (!rmethod->jit_wrapper) {
+ MonoMethod *method = rmethod->method;
+ MonoError error;
+
+ sig = mono_method_signature (method);
+ g_assert (sig);
+
+ MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
+ //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
+
+ gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
+ mono_error_assert_ok (&error);
+
+ gpointer addr = mono_jit_compile_method_jit_only (method, &error);
+ g_assert (addr);
+ mono_error_assert_ok (&error);
+
+ rmethod->jit_addr = addr;
+ rmethod->jit_sig = sig;
+ mono_memory_barrier ();
+ rmethod->jit_wrapper = jit_wrapper;
+
+ } else {
+ sig = rmethod->jit_sig;
+ }
+
+ sp -= sig->param_count;
+ if (sig->hasthis)
+ --sp;
+
+ ftndesc.addr = rmethod->jit_addr;
+ ftndesc.arg = NULL;
+
+ // FIXME: Optimize this
+
+ gpointer args [32];
+ int pindex = 0;
+ int stack_index = 0;
+ if (rmethod->hasthis) {
+ args [pindex ++] = sp [0].data.p;
+ stack_index ++;
+ }
+ type = rmethod->rtype;
+ if (type->type != MONO_TYPE_VOID) {
+ if (MONO_TYPE_ISSTRUCT (type))
+ args [pindex ++] = vt_sp;
+ else
+ args [pindex ++] = res_buf;
+ }
+ for (int i = 0; i < rmethod->param_count; ++i) {
+ MonoType *t = rmethod->param_types [i];
+ stackval *sval = &sp [stack_index + i];
+ if (sig->params [i]->byref) {
+ args [pindex ++] = sval->data.p;
+ } else if (MONO_TYPE_ISSTRUCT (t)) {
+ args [pindex ++] = sval->data.p;
+ } else if (MONO_TYPE_IS_REFERENCE (t)) {
+ args [pindex ++] = &sval->data.p;
+ } else {
+ switch (t->type) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_VALUETYPE:
+ args [pindex ++] = &sval->data.i;
+ break;
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_OBJECT:
+ args [pindex ++] = &sval->data.p;
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ args [pindex ++] = &sval->data.l;
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (t));
+ g_assert_not_reached ();
+ }
+ }
+ }
+
+ interp_push_lmf (&ext, frame);
+
+ switch (pindex) {
+ case 0: {
+ void (*func)(gpointer) = rmethod->jit_wrapper;
+
+ func (&ftndesc);
+ break;
+ }
+ case 1: {
+ void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], &ftndesc);
+ break;
+ }
+ case 2: {
+ void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], &ftndesc);
+ break;
+ }
+ case 3: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], &ftndesc);
+ break;
+ }
+ case 4: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], &ftndesc);
+ break;
+ }
+ case 5: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
+ break;
+ }
+ case 6: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
+ break;
+ }
+ case 7: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ interp_pop_lmf (&ext);
+
+ MonoType *rtype = rmethod->rtype;
+ switch (rtype->type) {
+ case MONO_TYPE_VOID:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ sp->data.p = *(gpointer*)res_buf;
+ break;
+ case MONO_TYPE_I1:
+ sp->data.i = *(gint8*)res_buf;
+ break;
+ case MONO_TYPE_U1:
+ sp->data.i = *(guint8*)res_buf;
+ break;
+ case MONO_TYPE_I2:
+ sp->data.i = *(gint16*)res_buf;
+ break;
+ case MONO_TYPE_U2:
+ sp->data.i = *(guint16*)res_buf;
+ break;
+ case MONO_TYPE_I4:
+ sp->data.i = *(gint32*)res_buf;
+ break;
+ case MONO_TYPE_U4:
+ sp->data.i = *(guint32*)res_buf;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ /* The result was written to vt_sp */
+ sp->data.p = vt_sp;
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (MONO_TYPE_IS_REFERENCE (rtype)) {
+ sp->data.p = *(gpointer*)res_buf;
+ } else {
+ /* The result was written to vt_sp */
+ sp->data.p = vt_sp;
+ }
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (rtype));
+ g_assert_not_reached ();
+ break;
+ }
+
+ return sp;
+}
+
+static void
+do_debugger_tramp (void (*tramp) (void), MonoInvocation *frame)
+{
+ MonoLMFExt ext;
+ interp_push_lmf (&ext, frame);
+ tramp ();
+ interp_pop_lmf (&ext);
+}
+
+static void
+do_transform_method (MonoInvocation *frame, ThreadContext *context)
+{
+ MonoLMFExt ext;
+
+ /* Use the parent frame as the current frame is not complete yet */
+ interp_push_lmf (&ext, frame->parent);
+
+ frame->ex = mono_interp_transform_method (frame->runtime_method, context);
+ context->managed_code = 1;
+
+ interp_pop_lmf (&ext);
+}
+
/*
* These functions are the entry points into the interpreter from compiled code.
* They are called by the interp_in wrappers. They have the following signature:
gpointer addr;
MonoMethodSignature *sig = mono_method_signature (method);
MonoMethod *wrapper;
- RuntimeMethod *rmethod;
+ RuntimeMethod *rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
/* HACK: method_ptr of delegate should point to a runtime method*/
if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
- return mono_interp_get_runtime_method (mono_domain_get (), method, error);
+ return rmethod;
- rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
if (rmethod->jit_entry)
return rmethod->jit_entry;
wrapper = mini_get_interp_in_wrapper (sig);
* rgctx register using a trampoline.
*/
- // FIXME: AOT
- g_assert (!mono_aot_only);
- addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
+ if (mono_aot_only)
+ addr = mono_aot_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
+ else
+ addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
mono_memory_barrier ();
rmethod->jit_entry = addr;
g_free (mn);
#endif
- MonoLMFExt ext;
-
- /* Use the parent frame as the current frame is not complete yet */
- interp_push_lmf (&ext, frame->parent);
-
- frame->ex = mono_interp_transform_method (frame->runtime_method, context);
- context->managed_code = 1;
-
- interp_pop_lmf (&ext);
-
+ do_transform_method (frame, context);
if (frame->ex) {
rtm = NULL;
ip = NULL;
MINT_IN_CASE(MINT_NOP)
++ip;
MINT_IN_BREAK;
- MINT_IN_CASE(MINT_BREAK) {
+ MINT_IN_CASE(MINT_BREAK)
++ip;
-
- MonoLMFExt ext;
-
- interp_push_lmf (&ext, frame);
-
- mono_debugger_agent_user_break ();
-
- interp_pop_lmf (&ext);
+ do_debugger_tramp (mono_debugger_agent_user_break, frame);
MINT_IN_BREAK;
- }
MINT_IN_CASE(MINT_LDNULL)
sp->data.p = NULL;
++ip;
--sp;
child_frame.stack_args = sp;
+#ifndef DISABLE_REMOTING
/* `this' can be NULL for string:.ctor */
if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
- child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+ child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
- child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
+ } else
+#endif
+ if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
--sp;
child_frame.stack_args = sp;
+#ifndef DISABLE_REMOTING
/* `this' can be NULL for string:.ctor */
if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
- child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+ child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
+#endif
ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
}
child_frame.stack_args = sp;
+#ifndef DISABLE_REMOTING
if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
- child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+ child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
+#endif
ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
}
MINT_IN_CASE(MINT_JIT_CALL) {
- MonoMethodSignature *sig;
RuntimeMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
- MonoFtnDesc ftndesc;
- guint8 res_buf [256];
- MonoType *type;
- MonoLMFExt ext;
-
- //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
-
- /*
- * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
- * by ref and return a return value using an explicit return value argument.
- */
- if (!rmethod->jit_wrapper) {
- MonoMethod *method = rmethod->method;
- MonoError error;
-
- sig = mono_method_signature (method);
- g_assert (sig);
-
- MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
- //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
-
- gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
- mono_error_assert_ok (&error);
-
- gpointer addr = mono_jit_compile_method_jit_only (method, &error);
- g_assert (addr);
- mono_error_assert_ok (&error);
-
- rmethod->jit_addr = addr;
- rmethod->jit_sig = sig;
- mono_memory_barrier ();
- rmethod->jit_wrapper = jit_wrapper;
-
- } else {
- sig = rmethod->jit_sig;
- }
-
frame->ip = ip;
ip += 2;
- sp -= sig->param_count;
- if (sig->hasthis)
- --sp;
-
- ftndesc.addr = rmethod->jit_addr;
- ftndesc.arg = NULL;
-
- // FIXME: Optimize this
-
- gpointer args [32];
- int pindex = 0;
- int stack_index = 0;
- if (rmethod->hasthis) {
- args [pindex ++] = sp [0].data.p;
- stack_index ++;
- }
- type = rmethod->rtype;
- if (type->type != MONO_TYPE_VOID) {
- if (MONO_TYPE_ISSTRUCT (type))
- args [pindex ++] = vt_sp;
- else
- args [pindex ++] = res_buf;
- }
- for (int i = 0; i < rmethod->param_count; ++i) {
- MonoType *t = rmethod->param_types [i];
- stackval *sval = &sp [stack_index + i];
- if (sig->params [i]->byref) {
- args [pindex ++] = sval->data.p;
- } else if (MONO_TYPE_ISSTRUCT (t)) {
- args [pindex ++] = sval->data.p;
- } else if (MONO_TYPE_IS_REFERENCE (t)) {
- args [pindex ++] = &sval->data.p;
- } else {
- switch (t->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_VALUETYPE:
- args [pindex ++] = &sval->data.i;
- break;
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_OBJECT:
- args [pindex ++] = &sval->data.p;
- break;
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- args [pindex ++] = &sval->data.l;
- break;
- default:
- printf ("%s\n", mono_type_full_name (t));
- g_assert_not_reached ();
- }
- }
- }
-
- interp_push_lmf (&ext, frame);
-
- switch (pindex) {
- case 0: {
- void (*func)(gpointer) = rmethod->jit_wrapper;
-
- func (&ftndesc);
- break;
- }
- case 1: {
- void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], &ftndesc);
- break;
- }
- case 2: {
- void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], &ftndesc);
- break;
- }
- case 3: {
- void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], args [2], &ftndesc);
- break;
- }
- case 4: {
- void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], args [2], args [3], &ftndesc);
- break;
- }
- case 5: {
- void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
- break;
- }
- case 6: {
- void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
- break;
- }
- case 7: {
- void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
- func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
- break;
- }
- default:
- g_assert_not_reached ();
- break;
- }
-
- interp_pop_lmf (&ext);
+ sp = do_jit_call (sp, vt_sp, context, frame, rmethod);
if (context->has_resume_state) {
/*
else
goto exit_frame;
}
-
- MonoType *rtype = rmethod->rtype;
- switch (rtype->type) {
- case MONO_TYPE_VOID:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- sp->data.p = *(gpointer*)res_buf;
- break;
- case MONO_TYPE_I1:
- sp->data.i = *(gint8*)res_buf;
- break;
- case MONO_TYPE_U1:
- sp->data.i = *(guint8*)res_buf;
- break;
- case MONO_TYPE_I2:
- sp->data.i = *(gint16*)res_buf;
- break;
- case MONO_TYPE_U2:
- sp->data.i = *(guint16*)res_buf;
- break;
- case MONO_TYPE_I4:
- sp->data.i = *(gint32*)res_buf;
- break;
- case MONO_TYPE_U4:
- sp->data.i = *(guint32*)res_buf;
- break;
- case MONO_TYPE_VALUETYPE:
- /* The result was written to vt_sp */
- sp->data.p = vt_sp;
- break;
- case MONO_TYPE_GENERICINST:
- if (MONO_TYPE_IS_REFERENCE (rtype)) {
- sp->data.p = *(gpointer*)res_buf;
- } else {
- /* The result was written to vt_sp */
- sp->data.p = vt_sp;
- }
- break;
- default:
- printf ("%s\n", mono_type_full_name (rtype));
- g_assert_not_reached ();
- break;
- }
- if (rtype->type != MONO_TYPE_VOID)
+ if (rmethod->rtype->type != MONO_TYPE_VOID)
sp++;
+
MINT_IN_BREAK;
}
this_arg = sp->data.p;
if (!this_arg)
THROW_EX (mono_get_exception_null_reference(), ip - 2);
- child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
+ child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
MonoClass *this_class = this_arg->vtable->klass;
if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
this_arg = sp->data.p;
if (!this_arg)
THROW_EX (mono_get_exception_null_reference(), ip - 2);
- child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
+ child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
MonoClass *this_class = this_arg->vtable->klass;
if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
MINT_IN_BREAK;
MINT_IN_CASE(MINT_LDIND_I8)
++ip;
- sp[-1].data.l = *(gint64*)sp[-1].data.p;
+ /* memmove handles unaligned case */
+ memmove (&sp [-1].data.l, sp [-1].data.p, sizeof (gint64));
MINT_IN_BREAK;
MINT_IN_CASE(MINT_LDIND_I) {
guint16 offset = * (guint16 *)(ip + 1);
if (newobj_class->parent == mono_defaults.array_class) {
sp -= csig->param_count;
child_frame.stack_args = sp;
- o = ves_array_create (&child_frame, context->domain, newobj_class, csig, sp);
+ o = ves_array_create (&child_frame, rtm->domain, newobj_class, csig, sp);
if (child_frame.ex)
THROW_EX (child_frame.ex, ip);
goto array_constructed;
} else {
if (newobj_class != mono_defaults.string_class) {
context->managed_code = 0;
- o = mono_object_new_checked (context->domain, newobj_class, &error);
+ o = mono_object_new_checked (rtm->domain, newobj_class, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
context->managed_code = 1;
if (*mono_thread_interruption_request_flag ())
THROW_EX (mono_get_exception_null_reference (), ip);
field = rtm->data_items[* (guint16 *)(ip + 1)];
ip += 2;
+#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- } else {
+ } else
+#endif
addr = (char*)o + field->offset;
- }
stackval_from_data (field->type, &sp [-1], addr, FALSE);
MINT_IN_BREAK;
field = rtm->data_items[* (guint16 *)(ip + 1)];
i32 = READ32(ip + 2);
ip += 4;
+#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- } else {
+ } else
+#endif
addr = (char*)o + field->offset;
- }
sp [-1].data.p = vt_sp;
memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
field = rtm->data_items[* (guint16 *)(ip + 1)];
ip += 2;
+#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
} else
+#endif
stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
sp -= 2;
i32 = READ32(ip + 2);
ip += 4;
+#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
} else
+#endif
memcpy((char*)o + field->offset, sp [-1].data.p, i32);
sp -= 2;
}
MINT_IN_CASE(MINT_LDSFLDA) {
MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
- sp->data.p = mono_class_static_field_address (context->domain, field);
+ sp->data.p = mono_class_static_field_address (rtm->domain, field);
ip += 2;
++sp;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_LDSFLD) {
MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
- gpointer addr = mono_class_static_field_address (context->domain, field);
+ gpointer addr = mono_class_static_field_address (rtm->domain, field);
stackval_from_data (field->type, sp, addr, FALSE);
ip += 2;
++sp;
}
MINT_IN_CASE(MINT_LDSFLD_VT) {
MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
- gpointer addr = mono_class_static_field_address (context->domain, field);
+ gpointer addr = mono_class_static_field_address (rtm->domain, field);
int size = READ32 (ip + 2);
ip += 4;
}
MINT_IN_CASE(MINT_STSFLD) {
MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
- gpointer addr = mono_class_static_field_address (context->domain, field);
+ gpointer addr = mono_class_static_field_address (rtm->domain, field);
ip += 2;
--sp;
stackval_to_data (field->type, sp, addr, FALSE);
}
MINT_IN_CASE(MINT_STSFLD_VT) {
MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
- gpointer addr = mono_class_static_field_address (context->domain, field);
+ gpointer addr = mono_class_static_field_address (rtm->domain, field);
int size = READ32 (ip + 2);
ip += 4;
if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
int size = mono_class_value_size (c, NULL);
- sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
+ sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, sp [-1 - offset].data.p, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
size = (size + 7) & ~7;
vt_sp -= size;
} else {
stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
- sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
+ sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, &sp [-1 - offset], &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
ip += 3;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_NEWARR)
- sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
+ sp [-1].data.p = (MonoObject*) mono_array_new_checked (rtm->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
if (!mono_error_ok (&error)) {
THROW_EX (mono_error_convert_to_exception (&error), ip);
}
++sp;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_MONO_NEWOBJ)
- sp->data.p = mono_object_new_checked (context->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
+ sp->data.p = mono_object_new_checked (rtm->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
ip += 2;
sp++;
MonoDomain *tls_domain = (MonoDomain *) ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
gpointer tls_jit = ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
- if (tls_domain != context->domain || !tls_jit)
- context->original_domain = mono_jit_thread_attach (context->domain);
+ if (tls_domain != rtm->domain || !tls_jit)
+ context->original_domain = mono_jit_thread_attach (rtm->domain);
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_MONO_JIT_DETACH)
MINT_IN_BREAK;
MINT_IN_CASE(MINT_SDB_INTR_LOC)
if (G_UNLIKELY (ss_enabled)) {
- MonoLMFExt ext;
static void (*ss_tramp) (void);
if (!ss_tramp) {
*/
frame->ip = ip + 1;
- interp_push_lmf (&ext, frame);
/*
* Use the same trampoline as the JIT. This ensures that
* the debugger has the context for the last interpreter
* native frame.
*/
- ss_tramp ();
- interp_pop_lmf (&ext);
+ do_debugger_tramp (ss_tramp, frame);
if (context->has_resume_state) {
if (frame == context->handler_frame)
++ip;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_SDB_BREAKPOINT) {
- MonoLMFExt ext;
-
static void (*bp_tramp) (void);
if (!bp_tramp) {
void *tramp = mini_get_breakpoint_trampoline ();
frame->ip = ip;
- interp_push_lmf (&ext, frame);
/* Use the same trampoline as the JIT */
- bp_tramp ();
- interp_pop_lmf (&ext);
+ do_debugger_tramp (bp_tramp, frame);
if (context->has_resume_state) {
if (frame == context->handler_frame)
if (!sp->data.p)
THROW_EX (mono_get_exception_null_reference (), ip - 2);
- sp->data.p = get_virtual_method (context->domain, m, sp->data.p);
+ sp->data.p = get_virtual_method (m, sp->data.p);
++sp;
MINT_IN_BREAK;
}
{
ThreadContext *context = mono_native_tls_get_value (thread_context_id);
ThreadContext context_struct;
+ MonoDomain *domain = frame->runtime_method->domain;
MonoError error;
jmp_buf env;
}
if (context == NULL) {
context = &context_struct;
- context_struct.domain = mono_domain_get ();
context_struct.base_frame = frame;
context_struct.current_frame = NULL;
context_struct.env_frame = frame;
}
frame->ip = NULL;
frame->parent = context->current_frame;
- frame->runtime_method = mono_interp_get_runtime_method (context->domain, frame->method, &error);
+ frame->runtime_method = mono_interp_get_runtime_method (domain, frame->method, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
context->managed_code = 1;
ves_exec_method_with_context (frame, context, NULL, NULL, -1);
MonoMethodHeader *header = mono_method_get_header (method);
MonoMethodSignature *signature = mono_method_signature (method);
MonoImage *image = method->klass->image;
- MonoDomain *domain = mono_domain_get ();
+ MonoDomain *domain = rtm->domain;
MonoClass *constrained_class = NULL;
MonoError error;
int offset, mt, i, i32;
MonoClass *field_klass = mono_class_from_mono_type (field->type);
mt = mint_type (&field_klass->byval_arg);
+#ifndef DISABLE_REMOTING
if (klass->marshalbyref) {
g_assert (!is_static);
ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_LDRMFLD_VT : MINT_LDRMFLD);
ADD_CODE(&td, get_data_item_index (&td, field));
- } else {
+ } else
+#endif
+ {
if (is_static) {
ADD_CODE (&td, MINT_POP);
ADD_CODE (&td, 0);
mono_class_init (klass);
mt = mint_type(field->type);
+#ifndef DISABLE_REMOTING
if (klass->marshalbyref) {
g_assert (!is_static);
ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_STRMFLD_VT : MINT_STRMFLD);
ADD_CODE(&td, get_data_item_index (&td, field));
- } else {
+ } else
+#endif
+ {
if (is_static) {
ADD_CODE (&td, MINT_POP);
ADD_CODE (&td, 1);
const MonoOpcode *opcode;
MonoMethod *m;
MonoClass *class;
- MonoDomain *domain = mono_domain_get ();
unsigned char *is_bb_start;
int in;
MonoVTable *method_class_vt;
int backwards;
MonoGenericContext *generic_context = NULL;
+ MonoDomain *domain = runtime_method->domain;
// g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
method_class_vt = mono_class_vtable (domain, runtime_method->method->klass);
}
#endif
-#if defined(__native_client_codegen__) || defined(__native_client__)
-/* When we cross-compile to Native Client we can't directly embed calls */
-/* to the math library on the host. This will use the fmod on the target*/
-double
-mono_fmod(double a, double b)
-{
- return fmod(a, b);
-}
-#endif
-
gpointer
mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
{
double mono_lconv_to_r8_un (guint64 a);
-#if defined(__native_client_codegen__) || defined(__native_client__)
-double mono_fmod(double a, double b);
-#endif
-
gpointer mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg);
MonoString*
* equivalent to mono_jit_set_aot_only (true) */
MONO_AOT_MODE_FULL,
/* Same as full, but use only llvm compiled code */
- MONO_AOT_MODE_LLVMONLY
+ MONO_AOT_MODE_LLVMONLY,
+ /* Uses Interpreter, JIT is disabled and not allowed,
+ * equivalent to "--full-aot --interpreter" */
+ MONO_AOT_MODE_INTERP
} MonoAotMode;
MONO_API void
return method;
}
-MonoClass*
-mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
-{
- MonoError error;
- MonoClass *klass;
-
- if (method->wrapper_type != MONO_WRAPPER_NONE) {
- klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- if (context) {
- klass = mono_class_inflate_generic_class_checked (klass, context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- }
- } else {
- klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- }
- if (klass)
- mono_class_init (klass);
- return klass;
-}
-
static inline MonoMethodSignature*
mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *context, MonoError *error)
{
#if defined(TARGET_WIN32)
need_touch = TRUE;
#elif defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
- if (!tree->flags & MONO_INST_INIT)
+ if (!(tree->flags & MONO_INST_INIT))
need_touch = TRUE;
#endif
return code;
}
-#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__) && !defined(MONO_CROSS_COMPILE)
+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(MONO_CROSS_COMPILE)
#define HAVE_AEABI_READ_TP 1
#endif
#define MONO_ARCH_DYN_CALL_SUPPORTED 1
#define MONO_ARCH_DYN_CALL_PARAM_AREA (DYN_CALL_STACK_ARGS * sizeof (mgreg_t))
-#ifndef MONO_CROSS_COMPILE
+#if !(defined(TARGET_ANDROID) && defined(MONO_CROSS_COMPILE))
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
#endif
#include "config.h"
#include "mini.h"
+#ifdef ENABLE_INTERPRETER
+#include "interp/interp.h"
+#endif
#include "tasklets.h"
#include <mono/metadata/abi-details.h>
#define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
#define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
#define MONO_ARCH_GSHARED_SUPPORTED 1
+#define MONO_ARCH_HAVE_INIT_LMF_EXT 1
/* set the next to 0 once inssel-mips.brg is updated */
#define MIPS_PASS_STRUCTS_BY_VALUE 1
#include <mach/clock.h>
#endif
-#if defined(__native_client__) || defined(HOST_WATCHOS)
+#if defined(HOST_WATCHOS)
void
mono_runtime_setup_stat_profiler (void)
#endif
-#endif /* defined(__native_client__) || defined(HOST_WATCHOS) */
-
-#if defined(__native_client__)
-
-void
-mono_gdb_render_native_backtraces (pid_t crashed_pid)
-{
-}
-
-#else
+#endif /* defined(HOST_WATCHOS) */
static gboolean
native_stack_with_gdb (pid_t crashed_pid, const char **argv, FILE *commands, char* commands_filename)
#endif // HAVE_EXECV
}
-#endif /* defined(__native_client__) */
-
#if !defined (__MACH__)
gboolean
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
#endif
#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
+#define MONO_ARCH_HAVE_INIT_LMF_EXT 1
#define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1)
#define PPC_NUM_REG_FPARGS (PPC_LAST_FPARG_REG-PPC_FIRST_FPARG_REG+1)
mono_jit_unlock ();
}
-#if defined(__native_client_codegen__) && defined(__native_client__)
-void
-mono_nacl_gc()
-{
-#ifdef __native_client_gc__
- __nacl_suspend_thread_if_needed();
-#endif
-}
-#endif /* __native_client__ */
-
/**
* mono_create_unwind_op:
*
break;
}
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
-#if defined(__native_client_codegen__)
- target = (gpointer)&__nacl_thread_suspension_needed;
-#else
g_assert (mono_threads_is_coop_enabled ());
target = (gpointer)&mono_polling_required;
-#endif
break;
case MONO_PATCH_INFO_SWITCH: {
gpointer *jump_table;
int i;
-#if defined(__native_client__) && defined(__native_client_codegen__)
- /* This memory will leak, but we don't care if we're */
- /* not deleting JIT'd methods anyway */
- jump_table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
-#else
if (method && method->dynamic) {
jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
jump_table = (void **)mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
}
}
-#endif
for (i = 0; i < patch_info->data.table->table_size; i++) {
jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
return lookup_method (domain, method);
}
+MonoClass*
+mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
+{
+ MonoError error;
+ MonoClass *klass;
+
+ if (method->wrapper_type != MONO_WRAPPER_NONE) {
+ klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
+ if (context) {
+ klass = mono_class_inflate_generic_class_checked (klass, context, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ }
+ } else {
+ klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ }
+ if (klass)
+ mono_class_init (klass);
+ return klass;
+}
+
#if ENABLE_JIT_MAP
static FILE* perf_map_file;
#ifdef MONO_USE_AOT_COMPILER
if (opt & MONO_OPT_AOT) {
- MonoDomain *domain = mono_domain_get ();
+ MonoDomain *domain = NULL;
+
+ if (mono_aot_mode == MONO_AOT_MODE_INTERP && method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+ g_assert (info);
+ if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
+ /* AOT'd wrappers for interp must be owned by root domain */
+ domain = mono_get_root_domain ();
+ }
+
+ if (!domain)
+ domain = mono_domain_get ();
mono_class_init (method->klass);
CHECKED_MONO_INIT ();
-#if defined(__linux__) && !defined(__native_client__)
+#if defined(__linux__)
if (access ("/proc/self/maps", F_OK) != 0) {
g_print ("Mono requires /proc to be mounted.\n");
exit (1);
register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
-#if defined(__native_client__) || defined(__native_client_codegen__)
- register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
-#endif
-
if (mono_threads_is_coop_enabled ())
register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, "mono_lconv_to_r8_un", FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_FREM
-#if !defined(__native_client__)
register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
-#else
- register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
-#endif
#endif
#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
#define MONO_ARCH_HAVE_DUMMY_INIT 1
#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
+#define MONO_ARCH_HAVE_INIT_LMF_EXT 1
/* Used for optimization, not complete */
#define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
}
case MONO_PATCH_INFO_SWITCH: {
gpointer *table;
-#if defined(__native_client__) && defined(__native_client_codegen__)
- /* This memory will leak. */
- /* TODO: can we free this when */
- /* making the final jump table? */
- table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
-#else
if (cfg->method->dynamic) {
table = (void **)mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
table = (void **)mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
}
-#endif
for (i = 0; i < patch_info->data.table->table_size; i++) {
/* Might be NULL if the switch is eliminated */
} else {
mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
}
-#if defined(__native_client_codegen__) && defined(__native_client__)
- cfg->native_code = code_dest;
-#endif
mono_profiler_code_buffer_new (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method);
mono_arch_flush_icache (cfg->native_code, cfg->code_len);
if (cfg->verbose_level > 1)
printf ("ADDING SAFE POINT TO BB %d\n", bblock->block_num);
-#if defined(__native_client_codegen__)
- NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&__nacl_thread_suspension_needed);
-#else
g_assert (mono_threads_is_coop_enabled ());
NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&mono_polling_required);
-#endif
MONO_INST_NEW (cfg, ins, OP_GC_SAFE_POINT);
ins->sreg1 = poll_addr->dreg;
{
MonoBasicBlock *bb;
-#if !defined(__native_client_codegen__)
if (!mono_threads_is_coop_enabled ())
return;
-#endif
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
-#if defined(__native_client__) || defined(__native_client_codegen__)
- gpointer poll_func = &mono_nacl_gc;
-#else
g_assert (mono_threads_is_coop_enabled ());
gpointer poll_func = &mono_threads_state_poll;
-#endif
if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && info->d.icall.func == poll_func) {
if (cfg->verbose_level > 1)
cfg->gen_seq_points = FALSE;
cfg->gen_sdb_seq_points = FALSE;
}
- /* coop / nacl requires loop detection to happen */
-#if defined(__native_client_codegen__)
- cfg->opt |= MONO_OPT_LOOP;
-#else
+ /* coop requires loop detection to happen */
if (mono_threads_is_coop_enabled ())
cfg->opt |= MONO_OPT_LOOP;
-#endif
cfg->explicit_null_checks = debug_options.explicit_null_checks || (flags & JIT_FLAG_EXPLICIT_NULL_CHECKS);
cfg->soft_breakpoints = debug_options.soft_breakpoints;
cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
}
}
- if (!mono_runtime_class_init_full (vtable, error))
- return NULL;
+ if (!(method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE ||
+ method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
+ method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE)) {
+ if (!mono_runtime_class_init_full (vtable, error))
+ return NULL;
+ }
return code;
}
#include "mono/metadata/security-manager.h"
#include "mono/metadata/exception.h"
-#ifdef __native_client_codegen__
-#include <nacl/nacl_dyncode.h>
-#endif
-
-
/*
* The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
* can be linked into both mono and mono-sgen.
MonoInst *stack_inbalance_var;
unsigned char *cil_start;
-#ifdef __native_client_codegen__
- /* this alloc is not aligned, native_code */
- /* is the 32-byte aligned version of this */
- unsigned char *native_code_alloc;
-#endif
unsigned char *native_code;
guint code_size;
guint code_len;
/* Native Client functions */
gpointer mono_realloc_native_code(MonoCompile *cfg);
-#if defined(__native_client__) || defined(__native_client_codegen__)
-extern volatile int __nacl_thread_suspension_needed;
-void __nacl_suspend_thread_if_needed(void);
-void mono_nacl_gc(void);
-#endif
-
extern MonoDebugOptions debug_options;
static inline MonoMethod*
void mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji);
void mono_arch_skip_single_step (MonoContext *ctx);
gpointer mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code);
+#endif
+
+#ifdef MONO_ARCH_HAVE_INIT_LMF_EXT
void mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf);
#endif
* \file
*/
-#if defined(__native_client__) && defined(__x86_64__)
-typedef guint64 regmask_t;
-#else
typedef size_t regmask_t;
-#endif
enum {
MONO_REG_INT,
g_assert_not_reached ();
return NULL;
}
-
+
+gpointer
+mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
#endif /* DISABLE_JIT */
guint8*
return NULL;
}
+gpointer
+mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
#endif /* !DISABLE_JIT */
return ((guint32*)plt_entry) [6];
#endif
}
+
+gpointer
+mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
return buf;
}
+gpointer
+mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
int expected = *(int*)ptr;
Intrinsics.UnalignedStobj<int> (ptr + 1, expected);
- if (Intrinsics.UnalignedLdobj<float> (ptr + 1) != f)
+ /* we can loose some precision due to r4<->r8 conversions */
+ if (Math.Abs (Intrinsics.UnalignedLdobj<float> (ptr + 1) - f) > 0.01f)
return 1;
return 0;
# FIXME fix the profiler tests to work with coop.
if !ENABLE_COOP
-if !NACL_CODEGEN
check_targets = testlog
endif
-endif
endif
endif
# also uses eglib (e.g. the runtime). Automake doesn't support this
# functionality, so create a separate static version of the library.
-libmono_profiler_aot_la_SOURCES = mono-profiler-aot.c
+libmono_profiler_aot_la_SOURCES = aot.c
libmono_profiler_aot_la_LIBADD = $(libmono_dep) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_aot_la_LDFLAGS = $(prof_ldflags)
-libmono_profiler_aot_static_la_SOURCES = mono-profiler-aot.c
+libmono_profiler_aot_static_la_SOURCES = aot.c
libmono_profiler_aot_static_la_LDFLAGS = -static
-libmono_profiler_iomap_la_SOURCES = mono-profiler-iomap.c
+libmono_profiler_iomap_la_SOURCES = iomap.c
libmono_profiler_iomap_la_LIBADD = $(libmono_dep) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_iomap_la_LDFLAGS = $(prof_ldflags)
-libmono_profiler_iomap_static_la_SOURCES = mono-profiler-iomap.c
+libmono_profiler_iomap_static_la_SOURCES = iomap.c
libmono_profiler_iomap_static_la_LDFLAGS = -static
-libmono_profiler_log_la_SOURCES = mono-profiler-log.c
+libmono_profiler_log_la_SOURCES = log.c log-args.c
libmono_profiler_log_la_LIBADD = $(libmono_dep) $(GLIB_LIBS) $(Z_LIBS)
libmono_profiler_log_la_LDFLAGS = $(prof_ldflags)
-libmono_profiler_log_static_la_SOURCES = mono-profiler-log.c
+libmono_profiler_log_static_la_SOURCES = log.c log-args.c
libmono_profiler_log_static_la_LDFLAGS = -static
if HAVE_VTUNE
-libmono_profiler_vtune_la_SOURCES = mono-profiler-vtune.c
+libmono_profiler_vtune_la_SOURCES = vtune.c
libmono_profiler_vtune_la_CFLAGS = $(VTUNE_CFLAGS)
libmono_profiler_vtune_la_LIBADD = $(VTUNE_LIBS) $(LIBMONO) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_vtune_la_LDFLAGS = $(prof_ldflags)
-libmono_profiler_vtune_static_la_SOURCES = mono-profiler-vtune.c
+libmono_profiler_vtune_static_la_SOURCES = vtune.c
libmono_profiler_vtune_static_la_LDFLAGS = -static
libmono_profiler_vtune_static_la_CFLAGS = $(VTUNE_CFLAGS)
libmono_profiler_vtune_static_la_LIBADD = $(VTUNE_LIBS)
check-local: $(check_targets)
-EXTRA_DIST=mono-profiler-log.h \
- mono-profiler-aot.h \
+EXTRA_DIST=log.h \
+ aot.h \
$(PLOG_TESTS_SRC) \
ptestrunner.pl \
$(suppression_DATA)
--- /dev/null
+/*
+ * mono-profiler-aot.c: Ahead of Time Compiler Profiler for Mono.
+ *
+ *
+ * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
+ *
+ * This profiler collects profiling information usable by the Mono AOT compiler
+ * to generate better code. It saves the information into files under ~/.mono.
+ * The AOT compiler can load these files during compilation.
+ * Currently, only the order in which methods were compiled is saved,
+ * allowing more efficient function ordering in the AOT files.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#include "aot.h"
+
+#include <mono/metadata/profiler.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/utils/mono-os-mutex.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <sys/stat.h>
+
+#ifdef HOST_WIN32
+#include <direct.h>
+#endif
+
+struct _MonoProfiler {
+ GHashTable *classes;
+ GHashTable *images;
+ GPtrArray *methods;
+ FILE *outfile;
+ int id;
+ char *outfile_name;
+};
+
+static mono_mutex_t mutex;
+static gboolean verbose;
+
+static void
+prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
+{
+}
+
+static void
+prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
+{
+ MonoImage *image = mono_class_get_image (mono_method_get_class (method));
+
+ if (!image->assembly || method->wrapper_type)
+ return;
+
+ mono_os_mutex_lock (&mutex);
+ g_ptr_array_add (prof->methods, method);
+ mono_os_mutex_unlock (&mutex);
+}
+
+static void
+prof_shutdown (MonoProfiler *prof);
+
+static void
+usage (int do_exit)
+{
+ printf ("AOT profiler.\n");
+ printf ("Usage: mono --profile=aot[:OPTION1[,OPTION2...]] program.exe\n");
+ printf ("Options:\n");
+ printf ("\thelp show this usage info\n");
+ printf ("\toutput=FILENAME write the data to file FILENAME (required)\n");
+ printf ("\tverbose print diagnostic info\n");
+ if (do_exit)
+ exit (1);
+}
+
+static const char*
+match_option (const char* p, const char *opt, char **rval)
+{
+ int len = strlen (opt);
+ if (strncmp (p, opt, len) == 0) {
+ if (rval) {
+ if (p [len] == '=' && p [len + 1]) {
+ const char *opt = p + len + 1;
+ const char *end = strchr (opt, ',');
+ char *val;
+ int l;
+ if (end == NULL) {
+ l = strlen (opt);
+ } else {
+ l = end - opt;
+ }
+ val = (char *) g_malloc (l + 1);
+ memcpy (val, opt, l);
+ val [l] = 0;
+ *rval = val;
+ return opt + l;
+ }
+ if (p [len] == 0 || p [len] == ',') {
+ *rval = NULL;
+ return p + len + (p [len] == ',');
+ }
+ usage (1);
+ } else {
+ if (p [len] == 0)
+ return p + len;
+ if (p [len] == ',')
+ return p + len + 1;
+ }
+ }
+ return p;
+}
+
+void
+mono_profiler_startup (const char *desc);
+
+/**
+ * mono_profiler_startup:
+ * the entry point
+ */
+void
+mono_profiler_startup (const char *desc)
+{
+ MonoProfiler *prof;
+ const char *p;
+ const char *opt;
+ char *outfile_name;
+
+ p = desc;
+ if (strncmp (p, "aot", 3))
+ usage (1);
+ p += 3;
+ if (*p == ':')
+ p++;
+ for (; *p; p = opt) {
+ char *val;
+ if (*p == ',') {
+ opt = p + 1;
+ continue;
+ }
+ if ((opt = match_option (p, "help", NULL)) != p) {
+ usage (0);
+ continue;
+ }
+ if ((opt = match_option (p, "verbose", NULL)) != p) {
+ verbose = TRUE;
+ continue;
+ }
+ if ((opt = match_option (p, "output", &val)) != p) {
+ outfile_name = val;
+ continue;
+ }
+ fprintf (stderr, "mono-profiler-aot: Unknown option: '%s'.\n", p);
+ exit (1);
+ }
+
+ if (!outfile_name) {
+ fprintf (stderr, "mono-profiler-aot: The 'output' argument is required.\n");
+ exit (1);
+ }
+
+ prof = g_new0 (MonoProfiler, 1);
+ prof->images = g_hash_table_new (NULL, NULL);
+ prof->classes = g_hash_table_new (NULL, NULL);
+ prof->methods = g_ptr_array_new ();
+ prof->outfile_name = outfile_name;
+
+ mono_os_mutex_init (&mutex);
+
+ mono_profiler_install (prof, prof_shutdown);
+
+ mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
+
+ mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+}
+
+static void
+emit_byte (MonoProfiler *prof, guint8 value)
+{
+ fwrite (&value, 1, 1, prof->outfile);
+}
+
+static void
+emit_int32 (MonoProfiler *prof, int value)
+{
+ // FIXME: Endianness
+ fwrite (&value, 4, 1, prof->outfile);
+}
+
+static void
+emit_string (MonoProfiler *prof, const char *str)
+{
+ int len = strlen (str);
+
+ emit_int32 (prof, len);
+ fwrite (str, len, 1, prof->outfile);
+}
+
+static void
+emit_record (MonoProfiler *prof, AotProfRecordType type, int id)
+{
+ emit_byte (prof, type);
+ emit_int32 (prof, id);
+}
+
+static int
+add_image (MonoProfiler *prof, MonoImage *image)
+{
+ int id = GPOINTER_TO_INT (g_hash_table_lookup (prof->images, image));
+ if (id)
+ return id - 1;
+
+ id = prof->id ++;
+ emit_record (prof, AOTPROF_RECORD_IMAGE, id);
+ emit_string (prof, image->assembly->aname.name);
+ emit_string (prof, image->guid);
+ g_hash_table_insert (prof->images, image, GINT_TO_POINTER (id + 1));
+ return id;
+}
+
+static int
+add_class (MonoProfiler *prof, MonoClass *klass);
+
+static int
+add_type (MonoProfiler *prof, MonoType *type)
+{
+ switch (type->type) {
+#if 0
+ case MONO_TYPE_SZARRAY: {
+ int eid = add_type (prof, &type->data.klass->byval_arg);
+ if (eid == -1)
+ return -1;
+ int id = prof->id ++;
+ emit_record (prof, AOTPROF_RECORD_TYPE, id);
+ emit_byte (prof, MONO_TYPE_SZARRAY);
+ emit_int32 (prof, id);
+ return id;
+ }
+#endif
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_GENERICINST:
+ return add_class (prof, mono_class_from_mono_type (type));
+ default:
+ return -1;
+ }
+}
+
+static int
+add_ginst (MonoProfiler *prof, MonoGenericInst *inst)
+{
+ int i, id;
+ int *ids;
+
+ // FIXME: Cache
+ ids = g_malloc0 (inst->type_argc * sizeof (int));
+ for (i = 0; i < inst->type_argc; ++i) {
+ MonoType *t = inst->type_argv [i];
+ ids [i] = add_type (prof, t);
+ if (ids [i] == -1) {
+ g_free (ids);
+ return -1;
+ }
+ }
+ id = prof->id ++;
+ emit_record (prof, AOTPROF_RECORD_GINST, id);
+ emit_int32 (prof, inst->type_argc);
+ for (i = 0; i < inst->type_argc; ++i)
+ emit_int32 (prof, ids [i]);
+ g_free (ids);
+
+ return id;
+}
+
+static int
+add_class (MonoProfiler *prof, MonoClass *klass)
+{
+ int id, inst_id = -1, image_id;
+ char *name;
+
+ id = GPOINTER_TO_INT (g_hash_table_lookup (prof->classes, klass));
+ if (id)
+ return id - 1;
+
+ image_id = add_image (prof, klass->image);
+
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericContext *ctx = mono_class_get_context (klass);
+ inst_id = add_ginst (prof, ctx->class_inst);
+ if (inst_id == -1)
+ return -1;
+ }
+
+ if (klass->nested_in)
+ name = g_strdup_printf ("%s.%s/%s", klass->nested_in->name_space, klass->nested_in->name, klass->name);
+ else
+ name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
+
+ id = prof->id ++;
+ emit_record (prof, AOTPROF_RECORD_TYPE, id);
+ emit_byte (prof, MONO_TYPE_CLASS);
+ emit_int32 (prof, image_id);
+ emit_int32 (prof, inst_id);
+ emit_string (prof, name);
+ g_free (name);
+ g_hash_table_insert (prof->classes, klass, GINT_TO_POINTER (id + 1));
+ return id;
+}
+
+static void
+add_method (MonoProfiler *prof, MonoMethod *m)
+{
+ MonoError error;
+ MonoMethodSignature *sig;
+ char *s;
+
+ sig = mono_method_signature_checked (m, &error);
+ g_assert (mono_error_ok (&error));
+
+ int class_id = add_class (prof, m->klass);
+ if (class_id == -1)
+ return;
+ int inst_id = -1;
+
+ if (m->is_inflated) {
+ MonoGenericContext *ctx = mono_method_get_context (m);
+ if (ctx->method_inst)
+ inst_id = add_ginst (prof, ctx->method_inst);
+ }
+ int id = prof->id ++;
+ emit_record (prof, AOTPROF_RECORD_METHOD, id);
+ emit_int32 (prof, class_id);
+ emit_int32 (prof, inst_id);
+ emit_int32 (prof, sig->param_count);
+ emit_string (prof, m->name);
+ s = mono_signature_full_name (sig);
+ emit_string (prof, s);
+ g_free (s);
+ if (verbose)
+ printf ("%s %d\n", mono_method_full_name (m, 1), id);
+}
+
+/* called at the end of the program */
+static void
+prof_shutdown (MonoProfiler *prof)
+{
+ FILE *outfile;
+ int mindex;
+ char magic [32];
+
+ printf ("Creating output file: %s\n", prof->outfile_name);
+
+ if (prof->outfile_name [0] == '#') {
+ int fd = strtol (prof->outfile_name + 1, NULL, 10);
+ outfile = fdopen (fd, "a");
+ } else {
+ outfile = fopen (prof->outfile_name, "w+");
+ }
+ if (!outfile) {
+ fprintf (stderr, "Unable to create output file '%s': %s.\n", prof->outfile_name, strerror (errno));
+ return;
+ }
+ prof->outfile = outfile;
+
+ gint32 version = (AOT_PROFILER_MAJOR_VERSION << 16) | AOT_PROFILER_MINOR_VERSION;
+ sprintf (magic, AOT_PROFILER_MAGIC);
+ fwrite (magic, strlen (magic), 1, outfile);
+ emit_int32 (prof, version);
+
+ GHashTable *all_methods = g_hash_table_new (NULL, NULL);
+ for (mindex = 0; mindex < prof->methods->len; ++mindex) {
+ MonoMethod *m = (MonoMethod*)g_ptr_array_index (prof->methods, mindex);
+
+ if (!mono_method_get_token (m))
+ continue;
+
+ if (g_hash_table_lookup (all_methods, m))
+ continue;
+ g_hash_table_insert (all_methods, m, m);
+
+ add_method (prof, m);
+ }
+ emit_record (prof, AOTPROF_RECORD_NONE, 0);
+
+ fclose (outfile);
+
+ g_hash_table_destroy (all_methods);
+ g_hash_table_destroy (prof->classes);
+ g_hash_table_destroy (prof->images);
+ g_ptr_array_free (prof->methods, TRUE);
+ g_free (prof->outfile_name);
+}
--- /dev/null
+#ifndef __MONO_PROFILER_AOT_H__
+#define __MONO_PROFILER_AOT_H__
+
+#include <config.h>
+
+/*
+ * File format:
+ * - magic
+ * - major/minor version as an int, i.e. 0x00010001
+ * - sequence of records terminated by a record with type TYPE_NONE
+ * Record format:
+ * - 1 byte record type (AotProfRecordType)
+ * - 1 int record id
+ * - record specific data
+ * Encoding rules:
+ * - int - 4 bytes little endian
+ * - string - int length followed by data
+ */
+
+typedef enum {
+ AOTPROF_RECORD_NONE,
+ AOTPROF_RECORD_IMAGE,
+ AOTPROF_RECORD_TYPE,
+ AOTPROF_RECORD_GINST,
+ AOTPROF_RECORD_METHOD
+} AotProfRecordType;
+
+#define AOT_PROFILER_MAGIC "AOTPROFILE"
+
+#define AOT_PROFILER_MAJOR_VERSION 1
+#define AOT_PROFILER_MINOR_VERSION 0
+
+#endif /* __MONO_PROFILER_AOT_H__ */
--- /dev/null
+/*
+ * mono-profiler-iomap.c: IOMAP string profiler for Mono.
+ *
+ * Authors:
+ * Marek Habersack <mhabersack@novell.com>
+ *
+ * Copyright (c) 2009 Novell, Inc (http://novell.com)
+ *
+ * Note: this profiler is completely unsafe wrt handling managed objects,
+ * don't use and don't copy code from here.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include "config.h"
+
+#include <string.h>
+#include <mono/utils/mono-io-portability.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/class.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/threads.h>
+#include <mono/metadata/profiler.h>
+#include <mono/metadata/loader.h>
+#include <mono/utils/mono-os-mutex.h>
+
+#define LOCATION_INDENT " "
+#define BACKTRACE_SIZE 64
+
+typedef struct _MonoStackBacktraceInfo
+{
+ MonoMethod *method;
+ gint native_offset;
+} MonoStackBacktraceInfo;
+
+typedef struct
+{
+ guint32 count;
+ gchar *requestedName;
+ gchar *actualName;
+} MismatchedFilesStats;
+
+typedef struct _SavedString
+{
+ MonoString *string;
+ MonoDomain *domain;
+ void *stack [BACKTRACE_SIZE];
+ gint stack_entries;
+ struct _SavedString *next;
+} SavedString;
+
+typedef struct _SavedStringFindInfo
+{
+ guint32 hash;
+ size_t len;
+} SavedStringFindInfo;
+
+typedef struct _StringLocation
+{
+ gchar *hint;
+ struct _StringLocation *next;
+} StringLocation;
+
+struct _MonoProfiler
+{
+ GHashTable *mismatched_files_hash;
+ GHashTable *saved_strings_hash;
+ GHashTable *string_locations_hash;
+ gboolean may_have_locations;
+};
+
+typedef struct _StackWalkData
+{
+ MonoProfiler *prof;
+ void **stack;
+ int stack_size;
+ int frame_count;
+} StackWalkData;
+
+static mono_mutex_t mismatched_files_section;
+static gboolean runtime_initialized = FALSE;
+
+static inline void append_report (GString **report, const gchar *format, ...);
+static inline void print_report (const gchar *format, ...);
+static inline guint32 do_calc_string_hash (guint32 hash, const gchar *str);
+static inline guint32 calc_strings_hash (const gchar *str1, const gchar *str2, guint32 *str1hash);
+static void print_mismatched_stats (MonoProfiler *prof);
+static inline gchar *build_hint (SavedString *head);
+static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries);
+static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len);
+static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str);
+void mono_profiler_startup (const char *desc);
+
+static void mismatched_stats_foreach_func (gpointer key, gpointer value, gpointer user_data)
+{
+ MismatchedFilesStats *stats = (MismatchedFilesStats*)value;
+ StringLocation *location;
+ MonoProfiler *prof = (MonoProfiler*)user_data;
+ guint32 hash;
+ gboolean bannerShown = FALSE;
+
+ hash = do_calc_string_hash (0, stats->requestedName);
+ fprintf (stdout,
+ " Count: %u\n"
+ "Requested: %s\n"
+ " Actual: %s\n",
+ stats->count, stats->requestedName, stats->actualName);
+
+ if (!prof->may_have_locations) {
+ fprintf (stdout, "\n");
+ return;
+ }
+
+ location = (StringLocation *)g_hash_table_lookup (prof->string_locations_hash, &hash);
+ while (location) {
+ if (location->hint && strlen (location->hint) > 0) {
+ if (!bannerShown) {
+ fprintf (stdout, "Locations:\n");
+ bannerShown = TRUE;
+ }
+ fprintf (stdout, "%s", location->hint);
+ }
+ location = location->next;
+ if (location)
+ fprintf (stdout, LOCATION_INDENT "--\n");
+ }
+
+ fprintf (stdout, "\n");
+}
+
+static void print_mismatched_stats (MonoProfiler *prof)
+{
+ if (!prof->mismatched_files_hash || g_hash_table_size (prof->mismatched_files_hash) == 0)
+ return;
+
+ prof->may_have_locations = g_hash_table_size (prof->string_locations_hash) > 0;
+
+ fprintf (stdout, "\n-=-=-=-=-=-=-= MONO_IOMAP Stats -=-=-=-=-=-=-=\n");
+ g_hash_table_foreach (prof->mismatched_files_hash, mismatched_stats_foreach_func, (gpointer)prof);
+ fflush (stdout);
+}
+
+static guint mismatched_files_guint32_hash (gconstpointer key)
+{
+ if (!key)
+ return 0;
+
+ return *((guint32*)key);
+}
+
+static gboolean mismatched_files_guint32_equal (gconstpointer key1, gconstpointer key2)
+{
+ if (!key1 || !key2)
+ return FALSE;
+
+ return (gboolean)(*((guint32*)key1) == *((guint32*)key2));
+}
+
+static inline guint32 do_calc_string_hash (guint32 hash, const gchar *str)
+{
+ guint32 ret = hash;
+ gchar *cc = (gchar*)str;
+ gchar *end = (gchar*)(str + strlen (str) - 1);
+
+ for (; cc < end; cc += 2) {
+ ret = (ret << 5) - ret + *cc;
+ ret = (ret << 5) - ret + cc [1];
+ }
+ end++;
+ if (cc < end)
+ ret = (ret << 5) - ret + *cc;
+
+ return ret;
+}
+
+static inline guint32 calc_strings_hash (const gchar *str1, const gchar *str2, guint32 *str1hash)
+{
+ guint32 hash = do_calc_string_hash (0, str1);
+ if (str1hash)
+ *str1hash = hash;
+ return do_calc_string_hash (hash, str2);
+}
+
+static inline void print_report (const gchar *format, ...)
+{
+ MonoError error;
+ MonoClass *klass;
+ MonoProperty *prop;
+ MonoString *str;
+ char *stack_trace;
+ va_list ap;
+
+ fprintf (stdout, "-=-=-=-=-=-=- MONO_IOMAP REPORT -=-=-=-=-=-=-\n");
+ va_start (ap, format);
+ vfprintf (stdout, format, ap);
+ fprintf (stdout, "\n");
+ va_end (ap);
+ klass = mono_class_load_from_name (mono_get_corlib (), "System", "Environment");
+ mono_class_init (klass);
+ prop = mono_class_get_property_from_name (klass, "StackTrace");
+ str = (MonoString*)mono_property_get_value_checked (prop, NULL, NULL, &error);
+ mono_error_assert_ok (&error);
+ stack_trace = mono_string_to_utf8_checked (str, &error);
+ mono_error_assert_ok (&error);
+
+ fprintf (stdout, "-= Stack Trace =-\n%s\n\n", stack_trace);
+ g_free (stack_trace);
+ fflush (stdout);
+}
+
+static inline void append_report (GString **report, const gchar *format, ...)
+{
+ va_list ap;
+ if (!*report)
+ *report = g_string_new ("");
+
+ va_start (ap, format);
+ g_string_append_vprintf (*report, format, ap);
+ va_end (ap);
+}
+
+static gboolean saved_strings_find_func (gpointer key, gpointer value, gpointer user_data)
+{
+ MonoError error;
+ SavedStringFindInfo *info = (SavedStringFindInfo*)user_data;
+ SavedString *saved = (SavedString*)value;
+ gchar *utf_str;
+ guint32 hash;
+
+ if (!info || !saved || mono_string_length (saved->string) != info->len)
+ return FALSE;
+
+ utf_str = mono_string_to_utf8_checked (saved->string, &error);
+ mono_error_assert_ok (&error);
+ hash = do_calc_string_hash (0, utf_str);
+ g_free (utf_str);
+
+ if (hash != info->hash)
+ return FALSE;
+
+ return TRUE;
+}
+
+static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len)
+{
+ StringLocation *location = (StringLocation *)g_hash_table_lookup (prof->string_locations_hash, &hash);
+ SavedString *saved;
+ SavedStringFindInfo info;
+ guint32 *hashptr;
+
+ if (location)
+ return;
+
+ info.hash = hash;
+ info.len = len;
+
+ /* Expensive but unavoidable... */
+ saved = (SavedString*)g_hash_table_find (prof->saved_strings_hash, saved_strings_find_func, &info);
+ hashptr = (guint32*)g_malloc (sizeof (guint32));
+ *hashptr = hash;
+ location = (StringLocation*)g_malloc0 (sizeof (location));
+
+ g_hash_table_insert (prof->string_locations_hash, hashptr, location);
+ if (!saved)
+ return;
+
+ g_hash_table_remove (prof->saved_strings_hash, saved->string);
+ location->hint = build_hint (saved);
+}
+
+static gboolean ignore_frame (MonoMethod *method)
+{
+ MonoClass *klass = method->klass;
+
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ return TRUE;
+
+ /* Now ignore the assemblies we know shouldn't contain mixed-case names (only the most frequent cases) */
+ if (klass->image ) {
+ if (strcmp (klass->image->assembly_name, "mscorlib") == 0)
+ return TRUE;
+ else if (strcmp (klass->image->assembly_name, "System") == 0)
+ return TRUE;
+ else if (strncmp (klass->image->assembly_name, "Mono.", 5) == 0)
+ return TRUE;
+ else if (strncmp (klass->image->assembly_name, "System.", 7) == 0)
+ return TRUE;
+ else if (strcmp (klass->image->assembly_name, "PEAPI") == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries)
+{
+ gchar *hint;
+ MonoMethod *method, *selectedMethod;
+ MonoAssembly *assembly;
+ MonoImage *image;
+ MonoDebugSourceLocation *location;
+ MonoStackBacktraceInfo *info;
+ gboolean use_full_trace;
+ char *methodName;
+ gint i, native_offset, firstAvailable;
+
+ selectedMethod = NULL;
+ firstAvailable = -1;
+ use_full_trace = FALSE;
+ native_offset = -1;
+ for (i = 0; i < stack_entries; i++) {
+ info = (MonoStackBacktraceInfo*) stack [i];
+ method = info ? info->method : NULL;
+
+ if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
+ continue;
+
+ if (firstAvailable == -1)
+ firstAvailable = i;
+
+ image = method->klass->image;
+ assembly = image->assembly;
+
+ if ((assembly && assembly->in_gac) || ignore_frame (method))
+ continue;
+ selectedMethod = method;
+ native_offset = info->native_offset;
+ break;
+ }
+
+ if (!selectedMethod) {
+ /* All the frames were from assemblies installed in GAC. Find first frame that is
+ * not in the ignore list */
+ for (i = 0; i < stack_entries; i++) {
+ info = (MonoStackBacktraceInfo*) stack [i];
+ method = info ? info->method : NULL;
+
+ if (!method || ignore_frame (method))
+ continue;
+ selectedMethod = method;
+ native_offset = info->native_offset;
+ break;
+ }
+
+ if (!selectedMethod)
+ use_full_trace = TRUE;
+ }
+
+ hint = NULL;
+ if (use_full_trace) {
+ GString *trace = g_string_new ("Full trace:\n");
+ for (i = firstAvailable; i < stack_entries; i++) {
+ info = (MonoStackBacktraceInfo*) stack [i];
+ method = info ? info->method : NULL;
+ if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
+ continue;
+
+ location = mono_debug_lookup_source_location (method, info->native_offset, domain);
+ methodName = mono_method_full_name (method, TRUE);
+
+ if (location) {
+ append_report (&trace, LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
+ mono_debug_free_source_location (location);
+ } else
+ append_report (&trace, LOCATION_INDENT "%s\n", methodName);
+ g_free (methodName);
+ }
+
+ if (trace) {
+ if (trace->len)
+ hint = g_string_free (trace, FALSE);
+ else
+ g_string_free (trace, TRUE);
+ }
+ } else {
+ location = mono_debug_lookup_source_location (selectedMethod, native_offset, domain);
+ methodName = mono_method_full_name (selectedMethod, TRUE);
+
+ if (location) {
+ hint = g_strdup_printf (LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
+ mono_debug_free_source_location (location);
+ } else
+ hint = g_strdup_printf (LOCATION_INDENT "%s\n", methodName);
+ g_free (methodName);
+ }
+
+ return hint;
+}
+
+static inline gchar *build_hint (SavedString *head)
+{
+ SavedString *current;
+ gchar *tmp;
+ GString *hint = NULL;
+
+ current = head;
+ while (current) {
+ tmp = build_hint_from_stack (current->domain, current->stack, current->stack_entries);
+ current = current->next;
+ if (!tmp)
+ continue;
+
+ append_report (&hint, tmp);
+ }
+
+ if (hint) {
+ if (hint->len)
+ return g_string_free (hint, FALSE);
+ else {
+ g_string_free (hint, FALSE);
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean stack_walk_func (MonoMethod *method, gint32 native_offset, gint32 il_offset, gboolean managed, gpointer data)
+{
+ StackWalkData *swdata = (StackWalkData*)data;
+ MonoStackBacktraceInfo *info;
+
+ if (swdata->frame_count >= swdata->stack_size)
+ return TRUE;
+
+ info = (MonoStackBacktraceInfo*)g_malloc (sizeof (*info));
+ info->method = method;
+ info->native_offset = native_offset;
+
+ swdata->stack [swdata->frame_count++] = info;
+ return FALSE;
+}
+
+static inline int mono_stack_backtrace (MonoProfiler *prof, MonoDomain *domain, void **stack, int size)
+{
+ StackWalkData data;
+
+ data.prof = prof;
+ data.stack = stack;
+ data.stack_size = size;
+ data.frame_count = 0;
+
+ mono_stack_walk_no_il (stack_walk_func, (gpointer)&data);
+
+ return data.frame_count;
+}
+
+static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str)
+{
+ SavedString *head, *entry;
+
+ if (!str || !domain || !runtime_initialized)
+ return;
+
+ entry = (SavedString*)g_malloc0 (sizeof (SavedString));
+ entry->string = str;
+ entry->domain = domain;
+ entry->stack_entries = mono_stack_backtrace (prof, domain, entry->stack, BACKTRACE_SIZE);
+ if (entry->stack_entries == 0) {
+ g_free (entry);
+ return;
+ }
+
+ mono_os_mutex_lock (&mismatched_files_section);
+ head = (SavedString*)g_hash_table_lookup (prof->saved_strings_hash, (gpointer)str);
+ if (head) {
+ while (head->next)
+ head = head->next;
+ head->next = entry;
+ } else
+ g_hash_table_insert (prof->saved_strings_hash, (gpointer)str, (gpointer)entry);
+ mono_os_mutex_unlock (&mismatched_files_section);
+}
+
+static MonoClass *string_class = NULL;
+
+static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+{
+ if (klass != string_class)
+ return;
+ mono_portability_remember_string (prof, mono_object_get_domain (obj), (MonoString*)obj);
+}
+
+static void mono_portability_iomap_event (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname)
+{
+ guint32 hash, pathnameHash;
+ MismatchedFilesStats *stats;
+
+ if (!runtime_initialized)
+ return;
+
+ mono_os_mutex_lock (&mismatched_files_section);
+ hash = calc_strings_hash (pathname, new_pathname, &pathnameHash);
+ stats = (MismatchedFilesStats*)g_hash_table_lookup (prof->mismatched_files_hash, &hash);
+ if (stats == NULL) {
+ guint32 *hashptr;
+
+ stats = (MismatchedFilesStats*) g_malloc (sizeof (MismatchedFilesStats));
+ stats->count = 1;
+ stats->requestedName = g_strdup (pathname);
+ stats->actualName = g_strdup (new_pathname);
+ hashptr = (guint32*)g_malloc (sizeof (guint32));
+ if (hashptr) {
+ *hashptr = hash;
+ g_hash_table_insert (prof->mismatched_files_hash, (gpointer)hashptr, stats);
+ } else
+ g_error ("Out of memory allocating integer pointer for mismatched files hash table.");
+
+ store_string_location (prof, (const gchar*)stats->requestedName, pathnameHash, strlen (stats->requestedName));
+ mono_os_mutex_unlock (&mismatched_files_section);
+
+ print_report ("%s - Found file path: '%s'\n", report, new_pathname);
+ } else {
+ mono_os_mutex_unlock (&mismatched_files_section);
+ stats->count++;
+ }
+}
+
+static void runtime_initialized_cb (MonoProfiler *prof)
+{
+ runtime_initialized = TRUE;
+ string_class = mono_get_string_class ();
+}
+
+static void profiler_shutdown (MonoProfiler *prof)
+{
+ print_mismatched_stats (prof);
+ mono_os_mutex_destroy (&mismatched_files_section);
+}
+
+void mono_profiler_startup (const char *desc)
+{
+ MonoProfiler *prof = g_new0 (MonoProfiler, 1);
+
+ mono_os_mutex_init (&mismatched_files_section);
+ prof->mismatched_files_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
+ prof->saved_strings_hash = g_hash_table_new (NULL, NULL);
+ prof->string_locations_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
+
+ mono_profiler_install (prof, profiler_shutdown);
+ mono_profiler_install_runtime_initialized (runtime_initialized_cb);
+ mono_profiler_install_iomap (mono_portability_iomap_event);
+ mono_profiler_install_allocation (mono_portability_remember_alloc);
+
+ mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_IOMAP_EVENTS));
+}
--- /dev/null
+#include <config.h>
+
+#include "log.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SCHED_GETAFFINITY
+#include <sched.h>
+
+# ifndef GLIBC_HAS_CPU_COUNT
+static int
+CPU_COUNT(cpu_set_t *set)
+{
+ int i, count = 0;
+
+ for (int i = 0; i < CPU_SETSIZE; i++)
+ if (CPU_ISSET(i, set))
+ count++;
+ return count;
+}
+# endif
+#endif
+
+typedef struct {
+ const char *event_name;
+ const int mask;
+} NameAndMask;
+
+static NameAndMask event_list[] = {
+ { "domain", PROFLOG_DOMAIN_EVENTS },
+ { "assembly", PROFLOG_ASSEMBLY_EVENTS },
+ { "module", PROFLOG_MODULE_EVENTS },
+ { "class", PROFLOG_CLASS_EVENTS },
+ { "jit", PROFLOG_JIT_COMPILATION_EVENTS },
+ { "exception", PROFLOG_EXCEPTION_EVENTS },
+ { "gcalloc", PROFLOG_ALLOCATION_EVENTS },
+ { "gc", PROFLOG_GC_EVENTS },
+ { "thread", PROFLOG_THREAD_EVENTS },
+ { "calls", PROFLOG_CALL_EVENTS },
+ //{ "inscov", PROFLOG_INS_COVERAGE_EVENTS }, //this is a profiler API event, but there's no actual event for us to emit here
+ //{ "sampling", PROFLOG_SAMPLING_EVENTS }, //it makes no sense to enable/disable this event by itself
+ { "monitor", PROFLOG_MONITOR_EVENTS },
+ { "gcmove", PROFLOG_GC_MOVES_EVENTS },
+ { "gcroot", PROFLOG_GC_ROOT_EVENTS },
+ { "context", PROFLOG_CONTEXT_EVENTS },
+ { "finalization", PROFLOG_FINALIZATION_EVENTS },
+ { "counter", PROFLOG_COUNTER_EVENTS },
+ { "gchandle", PROFLOG_GC_HANDLE_EVENTS },
+
+ { "typesystem", PROFLOG_TYPELOADING_ALIAS },
+ { "coverage", PROFLOG_CODECOV_ALIAS },
+ //{ "sample", PROFLOG_PERF_SAMPLING_ALIAS }, //takes args, explicitly handles
+ { "alloc", PROFLOG_GC_ALLOC_ALIAS },
+ //{ "heapshot", PROFLOG_HEAPSHOT_ALIAS }, //takes args, explicitly handled
+ { "legacy", PROFLOG_LEGACY_ALIAS },
+};
+
+static void usage (void);
+static void set_hsmode (ProfilerConfig *config, const char* val);
+static void set_sample_freq (ProfilerConfig *config, const char *val);
+static int mono_cpu_count (void);
+
+
+static gboolean
+match_option (const char *arg, const char *opt_name, const char **rval)
+{
+ if (rval) {
+ const char *end = strchr (arg, '=');
+
+ *rval = NULL;
+ if (!end)
+ return !strcmp (arg, opt_name);
+
+ if (strncmp (arg, opt_name, strlen (opt_name)) || (end - arg) > strlen (opt_name) + 1)
+ return FALSE;
+ *rval = end + 1;
+ return TRUE;
+ } else {
+ //FIXME how should we handle passing a value to an arg that doesn't expect it?
+ return !strcmp (arg, opt_name);
+ }
+}
+
+static void
+parse_arg (const char *arg, ProfilerConfig *config)
+{
+ const char *val;
+
+ if (match_option (arg, "help", NULL)) {
+ usage ();
+ } else if (match_option (arg, "report", NULL)) {
+ config->do_report = TRUE;
+ } else if (match_option (arg, "debug", NULL)) {
+ config->do_debug = TRUE;
+ } else if (match_option (arg, "debug-coverage", NULL)) {
+ config->debug_coverage = TRUE;
+ } else if (match_option (arg, "sampling-real", NULL)) {
+ config->sampling_mode = MONO_PROFILER_STAT_MODE_REAL;
+ } else if (match_option (arg, "sampling-process", NULL)) {
+ config->sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
+ } else if (match_option (arg, "heapshot", &val)) {
+ config->enable_mask |= PROFLOG_HEAPSHOT_ALIAS;
+ set_hsmode (config, val);
+ } else if (match_option (arg, "sample", &val)) {
+ config->enable_mask |= PROFLOG_PERF_SAMPLING_ALIAS;
+ set_sample_freq (config, val);
+ } else if (match_option (arg, "zip", NULL)) {
+ config->use_zip = TRUE;
+ } else if (match_option (arg, "output", &val)) {
+ config->output_filename = g_strdup (val);
+ } else if (match_option (arg, "port", &val)) {
+ char *end;
+ config->command_port = strtoul (val, &end, 10);
+ } else if (match_option (arg, "maxframes", &val)) {
+ char *end;
+ int num_frames = strtoul (val, &end, 10);
+ if (num_frames > MAX_FRAMES)
+ num_frames = MAX_FRAMES;
+ config->notraces = num_frames == 0;
+ config->num_frames = num_frames;
+ } else if (match_option (arg, "maxsamples", &val)) {
+ char *end;
+ int max_samples = strtoul (val, &end, 10);
+ if (max_samples)
+ config->max_allocated_sample_hits = max_samples;
+ } else if (match_option (arg, "calldepth", &val)) {
+ char *end;
+ config->max_call_depth = strtoul (val, &end, 10);
+ } else if (match_option (arg, "covfilter-file", &val)) {
+ if (config->cov_filter_files == NULL)
+ config->cov_filter_files = g_ptr_array_new ();
+ g_ptr_array_add (config->cov_filter_files, g_strdup (val));
+ } else if (match_option (arg, "onlycoverage", NULL)) {
+ config->only_coverage = TRUE;
+ } else {
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (event_list); ++i){
+ if (!strcmp (arg, event_list [i].event_name)) {
+ config->enable_mask |= event_list [i].mask;
+ break;
+ } else if (arg [0] == 'n' && arg [1] == 'o' && !strcmp (arg + 2, event_list [i].event_name)) {
+ config->disable_mask |= event_list [i].mask;
+ }
+ }
+ if (i == G_N_ELEMENTS (event_list)) {
+ printf ("Could not parse argument %s\n", arg);
+ }
+ }
+}
+
+static void
+load_args_from_env_or_default (ProfilerConfig *config)
+{
+ //XXX change this to header constants
+
+ config->max_allocated_sample_hits = mono_cpu_count () * 1000;
+ config->sample_freq = 100;
+ config->max_call_depth = 100;
+ config->num_frames = MAX_FRAMES;
+}
+
+
+void
+proflog_parse_args (ProfilerConfig *config, const char *desc)
+{
+ const char *p;
+ gboolean in_quotes = FALSE;
+ char quote_char = '\0';
+ char *buffer = malloc (strlen (desc));
+ int buffer_pos = 0;
+
+ load_args_from_env_or_default (config);
+
+ for (p = desc; *p; p++){
+ switch (*p){
+ case ',':
+ if (!in_quotes) {
+ if (buffer_pos != 0){
+ buffer [buffer_pos] = 0;
+ parse_arg (buffer, config);
+ buffer_pos = 0;
+ }
+ } else {
+ buffer [buffer_pos++] = *p;
+ }
+ break;
+
+ case '\\':
+ if (p [1]) {
+ buffer [buffer_pos++] = p[1];
+ p++;
+ }
+ break;
+ case '\'':
+ case '"':
+ if (in_quotes) {
+ if (quote_char == *p)
+ in_quotes = FALSE;
+ else
+ buffer [buffer_pos++] = *p;
+ } else {
+ in_quotes = TRUE;
+ quote_char = *p;
+ }
+ break;
+ default:
+ buffer [buffer_pos++] = *p;
+ break;
+ }
+ }
+
+ if (buffer_pos != 0) {
+ buffer [buffer_pos] = 0;
+ parse_arg (buffer, config);
+ }
+
+ g_free (buffer);
+
+ //Compure config effective mask
+ config->effective_mask = config->enable_mask & ~config->disable_mask;
+}
+
+static void
+set_hsmode (ProfilerConfig *config, const char* val)
+{
+ char *end;
+ unsigned int count;
+ if (!val)
+ return;
+ if (strcmp (val, "ondemand") == 0) {
+ config->hs_mode_ondemand = TRUE;
+ return;
+ }
+
+ count = strtoul (val, &end, 10);
+ if (val == end) {
+ usage ();
+ return;
+ }
+
+ if (strcmp (end, "ms") == 0)
+ config->hs_mode_ms = count;
+ else if (strcmp (end, "gc") == 0)
+ config->hs_mode_gc = count;
+ else
+ usage ();
+}
+
+/*
+Sampling frequency allows for one undocumented, hidden and ignored argument. The sampling kind.
+Back in the day when this was done using perf, we could specify one of: cycles,instr,cacherefs,cachemiss,branches,branchmiss
+With us moving ot userland sampling, those options are now meaningless.
+*/
+static void
+set_sample_freq (ProfilerConfig *config, const char *val)
+{
+ if (!val)
+ return;
+
+ const char *p = val;
+
+ // Is it only the frequency (new option style)?
+ if (isdigit (*p))
+ goto parse;
+
+ // Skip the sample type for backwards compatibility.
+ while (isalpha (*p))
+ p++;
+
+ // Skip the forward slash only if we got a sample type.
+ if (p != val && *p == '/') {
+ p++;
+
+ char *end;
+
+ parse:
+ config->sample_freq = strtoul (p, &end, 10);
+
+ if (p == end) {
+ usage ();
+ return;
+ }
+
+ p = end;
+ }
+
+ if (*p)
+ usage ();
+}
+
+static void
+usage (void)
+{
+ printf ("Log profiler version %d.%d (format: %d)\n", LOG_VERSION_MAJOR, LOG_VERSION_MINOR, LOG_DATA_VERSION);
+ printf ("Usage: mono --profile=log[:OPTION1[,OPTION2...]] program.exe\n");
+ printf ("Options:\n");
+ printf ("\thelp show this usage info\n");
+ printf ("\t[no]'event' enable/disable a profiling event. Valid values: domain, assembly, module, class, jit, exception, gcalloc, gc, thread, monitor, gcmove, gcroot, context, finalization, counter, gchandle\n");
+ printf ("\t[no]typesystem enable/disable typesystem related events such as class and assembly loading\n");
+ printf ("\t[no]alloc enable/disable recording allocation info\n");
+ printf ("\t[no]calls enable/disable recording enter/leave method events\n");
+ printf ("\t[no]legacy enable/disable pre mono 5.4 default profiler events\n");
+ printf ("\tsample[=frequency] enable/disable statistical sampling of threads (frequency in Hz, 100 by default)\n");
+ printf ("\theapshot[=MODE] record heap shot info (by default at each major collection)\n");
+ printf ("\t MODE: every XXms milliseconds, every YYgc collections, ondemand\n");
+ printf ("\t[no]coverage enable collection of code coverage data\n");
+ printf ("\tcovfilter=ASSEMBLY add an assembly to the code coverage filters\n");
+ printf ("\t add a + to include the assembly or a - to exclude it\n");
+ printf ("\t covfilter=-mscorlib\n");
+ printf ("\tcovfilter-file=FILE use FILE to generate the list of assemblies to be filtered\n");
+ printf ("\tmaxframes=NUM collect up to NUM stack frames\n");
+ printf ("\tcalldepth=NUM ignore method events for call chain depth bigger than NUM\n");
+ printf ("\toutput=FILENAME write the data to file FILENAME (The file is always overwriten)\n");
+ printf ("\toutput=|PROGRAM write the data to the stdin of PROGRAM\n");
+ printf ("\t %%t is subtituted with date and time, %%p with the pid\n");
+ printf ("\treport create a report instead of writing the raw data to a file\n");
+ printf ("\tzip compress the output data\n");
+ printf ("\tport=PORTNUM use PORTNUM for the listening command server\n");
+}
+
+static int
+mono_cpu_count (void)
+{
+#ifdef PLATFORM_ANDROID
+ /* Android tries really hard to save power by powering off CPUs on SMP phones which
+ * means the normal way to query cpu count returns a wrong value with userspace API.
+ * Instead we use /sys entries to query the actual hardware CPU count.
+ */
+ int count = 0;
+ char buffer[8] = {'\0'};
+ int present = open ("/sys/devices/system/cpu/present", O_RDONLY);
+ /* Format of the /sys entry is a cpulist of indexes which in the case
+ * of present is always of the form "0-(n-1)" when there is more than
+ * 1 core, n being the number of CPU cores in the system. Otherwise
+ * the value is simply 0
+ */
+ if (present != -1 && read (present, (char*)buffer, sizeof (buffer)) > 3)
+ count = strtol (((char*)buffer) + 2, NULL, 10);
+ if (present != -1)
+ close (present);
+ if (count > 0)
+ return count + 1;
+#endif
+
+#if defined(HOST_ARM) || defined (HOST_ARM64)
+
+ /* ARM platforms tries really hard to save power by powering off CPUs on SMP phones which
+ * means the normal way to query cpu count returns a wrong value with userspace API. */
+
+#ifdef _SC_NPROCESSORS_CONF
+ {
+ int count = sysconf (_SC_NPROCESSORS_CONF);
+ if (count > 0)
+ return count;
+ }
+#endif
+
+#else
+
+#ifdef HAVE_SCHED_GETAFFINITY
+ {
+ cpu_set_t set;
+ if (sched_getaffinity (getpid (), sizeof (set), &set) == 0)
+ return CPU_COUNT (&set);
+ }
+#endif
+#ifdef _SC_NPROCESSORS_ONLN
+ {
+ int count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count > 0)
+ return count;
+ }
+#endif
+
+#endif /* defined(HOST_ARM) || defined (HOST_ARM64) */
+
+#ifdef USE_SYSCTL
+ {
+ int count;
+ int mib [2];
+ size_t len = sizeof (int);
+ mib [0] = CTL_HW;
+ mib [1] = HW_NCPU;
+ if (sysctl (mib, 2, &count, &len, NULL, 0) == 0)
+ return count;
+ }
+#endif
+#ifdef HOST_WIN32
+ {
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ return info.dwNumberOfProcessors;
+ }
+#endif
+
+ static gboolean warned;
+
+ if (!warned) {
+ g_warning ("Don't know how to determine CPU count on this platform; assuming 1");
+ warned = TRUE;
+ }
+
+ return 1;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * mono-profiler-log.c: mono log profiler
+ *
+ * Authors:
+ * Paolo Molaro (lupus@ximian.com)
+ * Alex Rønne Petersen (alexrp@xamarin.com)
+ *
+ * Copyright 2010 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/debug-helpers.h>
+#include "../metadata/metadata-internals.h"
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/mono-gc.h>
+#include <mono/metadata/mono-perfcounters.h>
+#include <mono/utils/atomic.h>
+#include <mono/utils/hazard-pointer.h>
+#include <mono/utils/lock-free-alloc.h>
+#include <mono/utils/lock-free-queue.h>
+#include <mono/utils/mono-conc-hashtable.h>
+#include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-linked-list-set.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-os-mutex.h>
+#include <mono/utils/mono-os-semaphore.h>
+#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-api.h>
+#include "log.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINK_H
+#include <link.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(__APPLE__)
+#include <mach/mach_time.h>
+#endif
+#include <netinet/in.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <sys/socket.h>
+#if defined (HAVE_SYS_ZLIB)
+#include <zlib.h>
+#endif
+
+#define BUFFER_SIZE (4096 * 16)
+
+/* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
+#define LEB128_SIZE 10
+
+/* Size of a value encoded as a single byte. */
+#undef BYTE_SIZE // mach/i386/vm_param.h on OS X defines this to 8, but it isn't used for anything.
+#define BYTE_SIZE 1
+
+/* Size in bytes of the event prefix (ID + time). */
+#define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
+
+static volatile gint32 runtime_inited;
+static volatile gint32 in_shutdown;
+
+static int nocalls = 0;
+static int notraces = 0;
+static int use_zip = 0;
+static int do_report = 0;
+static int do_heap_shot = 0;
+static int max_call_depth = 0;
+static int command_port = 0;
+static int heapshot_requested = 0;
+static int do_mono_sample = 0;
+static int do_debug = 0;
+static int do_coverage = 0;
+static gboolean no_counters = FALSE;
+static gboolean only_coverage = FALSE;
+static gboolean debug_coverage = FALSE;
+static int max_allocated_sample_hits;
+
+// Statistics for internal profiler data structures.
+static gint32 sample_allocations_ctr,
+ buffer_allocations_ctr;
+
+// Statistics for profiler events.
+static gint32 sync_points_ctr,
+ heap_objects_ctr,
+ heap_starts_ctr,
+ heap_ends_ctr,
+ heap_roots_ctr,
+ gc_events_ctr,
+ gc_resizes_ctr,
+ gc_allocs_ctr,
+ gc_moves_ctr,
+ gc_handle_creations_ctr,
+ gc_handle_deletions_ctr,
+ finalize_begins_ctr,
+ finalize_ends_ctr,
+ finalize_object_begins_ctr,
+ finalize_object_ends_ctr,
+ image_loads_ctr,
+ image_unloads_ctr,
+ assembly_loads_ctr,
+ assembly_unloads_ctr,
+ class_loads_ctr,
+ class_unloads_ctr,
+ method_entries_ctr,
+ method_exits_ctr,
+ method_exception_exits_ctr,
+ method_jits_ctr,
+ code_buffers_ctr,
+ exception_throws_ctr,
+ exception_clauses_ctr,
+ monitor_contentions_ctr,
+ monitor_acquisitions_ctr,
+ monitor_failures_ctr,
+ thread_starts_ctr,
+ thread_ends_ctr,
+ thread_names_ctr,
+ domain_loads_ctr,
+ domain_unloads_ctr,
+ domain_names_ctr,
+ context_loads_ctr,
+ context_unloads_ctr,
+ sample_ubins_ctr,
+ sample_usyms_ctr,
+ sample_hits_ctr,
+ counter_descriptors_ctr,
+ counter_samples_ctr,
+ perfcounter_descriptors_ctr,
+ perfcounter_samples_ctr,
+ coverage_methods_ctr,
+ coverage_statements_ctr,
+ coverage_classes_ctr,
+ coverage_assemblies_ctr;
+
+static MonoLinkedListSet profiler_thread_list;
+
+/*
+ * file format:
+ * [header] [buffer]*
+ *
+ * The file is composed by a header followed by 0 or more buffers.
+ * Each buffer contains events that happened on a thread: for a given thread
+ * buffers that appear later in the file are guaranteed to contain events
+ * that happened later in time. Buffers from separate threads could be interleaved,
+ * though.
+ * Buffers are not required to be aligned.
+ *
+ * header format:
+ * [id: 4 bytes] constant value: LOG_HEADER_ID
+ * [major: 1 byte] [minor: 1 byte] major and minor version of the log profiler
+ * [format: 1 byte] version of the data format for the rest of the file
+ * [ptrsize: 1 byte] size in bytes of a pointer in the profiled program
+ * [startup time: 8 bytes] time in milliseconds since the unix epoch when the program started
+ * [timer overhead: 4 bytes] approximate overhead in nanoseconds of the timer
+ * [flags: 4 bytes] file format flags, should be 0 for now
+ * [pid: 4 bytes] pid of the profiled process
+ * [port: 2 bytes] tcp port for server if != 0
+ * [args size: 4 bytes] size of args
+ * [args: string] arguments passed to the profiler
+ * [arch size: 4 bytes] size of arch
+ * [arch: string] architecture the profiler is running on
+ * [os size: 4 bytes] size of os
+ * [os: string] operating system the profiler is running on
+ *
+ * The multiple byte integers are in little-endian format.
+ *
+ * buffer format:
+ * [buffer header] [event]*
+ * Buffers have a fixed-size header followed by 0 or more bytes of event data.
+ * Timing information and other values in the event data are usually stored
+ * as uleb128 or sleb128 integers. To save space, as noted for each item below,
+ * some data is represented as a difference between the actual value and
+ * either the last value of the same type (like for timing information) or
+ * as the difference from a value stored in a buffer header.
+ *
+ * For timing information the data is stored as uleb128, since timing
+ * increases in a monotonic way in each thread: the value is the number of
+ * nanoseconds to add to the last seen timing data in a buffer. The first value
+ * in a buffer will be calculated from the time_base field in the buffer head.
+ *
+ * Object or heap sizes are stored as uleb128.
+ * Pointer differences are stored as sleb128, instead.
+ *
+ * If an unexpected value is found, the rest of the buffer should be ignored,
+ * as generally the later values need the former to be interpreted correctly.
+ *
+ * buffer header format:
+ * [bufid: 4 bytes] constant value: BUF_ID
+ * [len: 4 bytes] size of the data following the buffer header
+ * [time_base: 8 bytes] time base in nanoseconds since an unspecified epoch
+ * [ptr_base: 8 bytes] base value for pointers
+ * [obj_base: 8 bytes] base value for object addresses
+ * [thread id: 8 bytes] system-specific thread ID (pthread_t for example)
+ * [method_base: 8 bytes] base value for MonoMethod pointers
+ *
+ * event format:
+ * [extended info: upper 4 bits] [type: lower 4 bits]
+ * [time diff: uleb128] nanoseconds since last timing
+ * [data]*
+ * The data that follows depends on type and the extended info.
+ * Type is one of the enum values in mono-profiler-log.h: TYPE_ALLOC, TYPE_GC,
+ * TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
+ * The extended info bits are interpreted based on type, see
+ * each individual event description below.
+ * strings are represented as a 0-terminated utf8 sequence.
+ *
+ * backtrace format:
+ * [num: uleb128] number of frames following
+ * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ *
+ * type alloc format:
+ * type: TYPE_ALLOC
+ * exinfo: flags: TYPE_ALLOC_BT
+ * [ptr: sleb128] class as a byte difference from ptr_base
+ * [obj: sleb128] object address as a byte difference from obj_base
+ * [size: uleb128] size of the object in the heap
+ * If the TYPE_ALLOC_BT flag is set, a backtrace follows.
+ *
+ * type GC format:
+ * type: TYPE_GC
+ * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
+ * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
+ * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
+ * if exinfo == TYPE_GC_RESIZE
+ * [heap_size: uleb128] new heap size
+ * if exinfo == TYPE_GC_EVENT
+ * [event type: byte] GC event (MONO_GC_EVENT_* from profiler.h)
+ * [generation: byte] GC generation event refers to
+ * if exinfo == TYPE_GC_MOVE
+ * [num_objects: uleb128] number of object moves that follow
+ * [objaddr: sleb128]+ num_objects object pointer differences from obj_base
+ * num is always an even number: the even items are the old
+ * addresses, the odd numbers are the respective new object addresses
+ * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
+ * [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
+ * upper bits reserved as flags
+ * [handle: uleb128] GC handle value
+ * [objaddr: sleb128] object pointer differences from obj_base
+ * If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
+ * [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
+ * upper bits reserved as flags
+ * [handle: uleb128] GC handle value
+ * If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_FINALIZE_OBJECT_{START,END}
+ * [object: sleb128] the object as a difference from obj_base
+ *
+ * type metadata format:
+ * type: TYPE_METADATA
+ * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN)
+ * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
+ * TYPE_THREAD, TYPE_CONTEXT
+ * [pointer: sleb128] pointer of the metadata type depending on mtype
+ * if mtype == TYPE_CLASS
+ * [image: sleb128] MonoImage* as a pointer difference from ptr_base
+ * [name: string] full class name
+ * if mtype == TYPE_IMAGE
+ * [name: string] image file name
+ * if mtype == TYPE_ASSEMBLY
+ * [name: string] assembly name
+ * if mtype == TYPE_DOMAIN && exinfo == 0
+ * [name: string] domain friendly name
+ * if mtype == TYPE_CONTEXT
+ * [domain: sleb128] domain id as pointer
+ * if mtype == TYPE_THREAD && exinfo == 0
+ * [name: string] thread name
+ *
+ * type method format:
+ * type: TYPE_METHOD
+ * exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
+ * [method: sleb128] MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ * if exinfo == TYPE_JIT
+ * [code address: sleb128] pointer to the native code as a diff from ptr_base
+ * [code size: uleb128] size of the generated code
+ * [name: string] full method name
+ *
+ * type exception format:
+ * type: TYPE_EXCEPTION
+ * exinfo: TYPE_THROW_BT flag or one of: TYPE_CLAUSE
+ * if exinfo == TYPE_CLAUSE
+ * [clause type: byte] MonoExceptionEnum enum value
+ * [clause index: uleb128] index of the current clause
+ * [method: sleb128] MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ * else
+ * [object: sleb128] the exception object as a difference from obj_base
+ * if exinfo has TYPE_THROW_BT set, a backtrace follows.
+ *
+ * type runtime format:
+ * type: TYPE_RUNTIME
+ * exinfo: one of: TYPE_JITHELPER
+ * if exinfo == TYPE_JITHELPER
+ * [type: byte] MonoProfilerCodeBufferType enum value
+ * [buffer address: sleb128] pointer to the native code as a diff from ptr_base
+ * [buffer size: uleb128] size of the generated code
+ * if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
+ * [name: string] buffer description name
+ *
+ * type monitor format:
+ * type: TYPE_MONITOR
+ * exinfo: TYPE_MONITOR_BT flag and one of: MONO_PROFILER_MONITOR_(CONTENTION|FAIL|DONE)
+ * [object: sleb128] the lock object as a difference from obj_base
+ * if exinfo.low3bits == MONO_PROFILER_MONITOR_CONTENTION
+ * If the TYPE_MONITOR_BT flag is set, a backtrace follows.
+ *
+ * type heap format
+ * type: TYPE_HEAP
+ * exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
+ * if exinfo == TYPE_HEAP_OBJECT
+ * [object: sleb128] the object as a difference from obj_base
+ * [class: sleb128] the object MonoClass* as a difference from ptr_base
+ * [size: uleb128] size of the object on the heap
+ * [num_refs: uleb128] number of object references
+ * each referenced objref is preceded by a uleb128 encoded offset: the
+ * first offset is from the object address and each next offset is relative
+ * to the previous one
+ * [objrefs: sleb128]+ object referenced as a difference from obj_base
+ * The same object can appear multiple times, but only the first time
+ * with size != 0: in the other cases this data will only be used to
+ * provide additional referenced objects.
+ * if exinfo == TYPE_HEAP_ROOT
+ * [num_roots: uleb128] number of root references
+ * [num_gc: uleb128] number of major gcs
+ * [object: sleb128] the object as a difference from obj_base
+ * [root_type: byte] the root_type: MonoProfileGCRootType (profiler.h)
+ * [extra_info: uleb128] the extra_info value
+ * object, root_type and extra_info are repeated num_roots times
+ *
+ * type sample format
+ * type: TYPE_SAMPLE
+ * exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
+ * if exinfo == TYPE_SAMPLE_HIT
+ * [thread: sleb128] thread id as difference from ptr_base
+ * [count: uleb128] number of following instruction addresses
+ * [ip: sleb128]* instruction pointer as difference from ptr_base
+ * [mbt_count: uleb128] number of managed backtrace frames
+ * [method: sleb128]* MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
+ * if exinfo == TYPE_SAMPLE_USYM
+ * [address: sleb128] symbol address as a difference from ptr_base
+ * [size: uleb128] symbol size (may be 0 if unknown)
+ * [name: string] symbol name
+ * if exinfo == TYPE_SAMPLE_UBIN
+ * [address: sleb128] address where binary has been loaded
+ * [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
+ * [size: uleb128] memory size
+ * [name: string] binary name
+ * if exinfo == TYPE_SAMPLE_COUNTERS_DESC
+ * [len: uleb128] number of counters
+ * for i = 0 to len
+ * [section: uleb128] section of counter
+ * if section == MONO_COUNTER_PERFCOUNTERS:
+ * [section_name: string] section name of counter
+ * [name: string] name of counter
+ * [type: byte] type of counter
+ * [unit: byte] unit of counter
+ * [variance: byte] variance of counter
+ * [index: uleb128] unique index of counter
+ * if exinfo == TYPE_SAMPLE_COUNTERS
+ * while true:
+ * [index: uleb128] unique index of counter
+ * if index == 0:
+ * break
+ * [type: byte] type of counter value
+ * if type == string:
+ * if value == null:
+ * [0: uleb128] 0 -> value is null
+ * else:
+ * [1: uleb128] 1 -> value is not null
+ * [value: string] counter value
+ * else:
+ * [value: uleb128/sleb128/double] counter value, can be sleb128, uleb128 or double (determined by using type)
+ *
+ * type coverage format
+ * type: TYPE_COVERAGE
+ * exinfo: one of TYPE_COVERAGE_METHOD, TYPE_COVERAGE_STATEMENT, TYPE_COVERAGE_ASSEMBLY, TYPE_COVERAGE_CLASS
+ * if exinfo == TYPE_COVERAGE_METHOD
+ * [assembly: string] name of assembly
+ * [class: string] name of the class
+ * [name: string] name of the method
+ * [signature: string] the signature of the method
+ * [filename: string] the file path of the file that contains this method
+ * [token: uleb128] the method token
+ * [method_id: uleb128] an ID for this data to associate with the buffers of TYPE_COVERAGE_STATEMENTS
+ * [len: uleb128] the number of TYPE_COVERAGE_BUFFERS associated with this method
+ * if exinfo == TYPE_COVERAGE_STATEMENTS
+ * [method_id: uleb128] an the TYPE_COVERAGE_METHOD buffer to associate this with
+ * [offset: uleb128] the il offset relative to the previous offset
+ * [counter: uleb128] the counter for this instruction
+ * [line: uleb128] the line of filename containing this instruction
+ * [column: uleb128] the column containing this instruction
+ * if exinfo == TYPE_COVERAGE_ASSEMBLY
+ * [name: string] assembly name
+ * [guid: string] assembly GUID
+ * [filename: string] assembly filename
+ * [number_of_methods: uleb128] the number of methods in this assembly
+ * [fully_covered: uleb128] the number of fully covered methods
+ * [partially_covered: uleb128] the number of partially covered methods
+ * currently partially_covered will always be 0, and fully_covered is the
+ * number of methods that are fully and partially covered.
+ * if exinfo == TYPE_COVERAGE_CLASS
+ * [name: string] assembly name
+ * [class: string] class name
+ * [number_of_methods: uleb128] the number of methods in this class
+ * [fully_covered: uleb128] the number of fully covered methods
+ * [partially_covered: uleb128] the number of partially covered methods
+ * currently partially_covered will always be 0, and fully_covered is the
+ * number of methods that are fully and partially covered.
+ *
+ * type meta format:
+ * type: TYPE_META
+ * exinfo: one of: TYPE_SYNC_POINT
+ * if exinfo == TYPE_SYNC_POINT
+ * [type: byte] MonoProfilerSyncPointType enum value
+ */
+
+// Pending data to be written to the log, for a single thread.
+// Threads periodically flush their own LogBuffers by calling safe_send
+typedef struct _LogBuffer LogBuffer;
+struct _LogBuffer {
+ // Next (older) LogBuffer in processing queue
+ LogBuffer *next;
+
+ uint64_t time_base;
+ uint64_t last_time;
+ uintptr_t ptr_base;
+ uintptr_t method_base;
+ uintptr_t last_method;
+ uintptr_t obj_base;
+ uintptr_t thread_id;
+
+ // Bytes allocated for this LogBuffer
+ int size;
+
+ // Start of currently unused space in buffer
+ unsigned char* cursor;
+
+ // Pointer to start-of-structure-plus-size (for convenience)
+ unsigned char* buf_end;
+
+ // Start of data in buffer. Contents follow "buffer format" described above.
+ unsigned char buf [1];
+};
+
+typedef struct {
+ MonoLinkedListSetNode node;
+
+ // Convenience pointer to the profiler structure.
+ MonoProfiler *profiler;
+
+ // Was this thread added to the LLS?
+ gboolean attached;
+
+ // The current log buffer for this thread.
+ LogBuffer *buffer;
+
+ // Methods referenced by events in `buffer`, see `MethodInfo`.
+ GPtrArray *methods;
+
+ // Current call depth for enter/leave events.
+ int call_depth;
+
+ // Indicates whether this thread is currently writing to its `buffer`.
+ gboolean busy;
+
+ // Has this thread written a thread end event to `buffer`?
+ gboolean ended;
+} MonoProfilerThread;
+
+static uintptr_t
+thread_id (void)
+{
+ return (uintptr_t) mono_native_thread_id_get ();
+}
+
+static uintptr_t
+process_id (void)
+{
+#ifdef HOST_WIN32
+ return (uintptr_t) GetCurrentProcessId ();
+#else
+ return (uintptr_t) getpid ();
+#endif
+}
+
+#ifdef __APPLE__
+static mach_timebase_info_data_t timebase_info;
+#elif defined (HOST_WIN32)
+static LARGE_INTEGER pcounter_freq;
+#endif
+
+#define TICKS_PER_SEC 1000000000LL
+
+static uint64_t
+current_time (void)
+{
+#ifdef __APPLE__
+ uint64_t time = mach_absolute_time ();
+
+ time *= timebase_info.numer;
+ time /= timebase_info.denom;
+
+ return time;
+#elif defined (HOST_WIN32)
+ LARGE_INTEGER value;
+
+ QueryPerformanceCounter (&value);
+
+ return value.QuadPart * TICKS_PER_SEC / pcounter_freq.QuadPart;
+#elif defined (CLOCK_MONOTONIC)
+ struct timespec tspec;
+
+ clock_gettime (CLOCK_MONOTONIC, &tspec);
+
+ return ((uint64_t) tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec);
+#else
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+
+ return ((uint64_t) tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000);
+#endif
+}
+
+static int timer_overhead;
+
+static void
+init_time (void)
+{
+#ifdef __APPLE__
+ mach_timebase_info (&timebase_info);
+#elif defined (HOST_WIN32)
+ QueryPerformanceFrequency (&pcounter_freq);
+#endif
+
+ uint64_t time_start = current_time ();
+
+ for (int i = 0; i < 256; ++i)
+ current_time ();
+
+ uint64_t time_end = current_time ();
+
+ timer_overhead = (time_end - time_start) / 256;
+}
+
+/*
+ * These macros should be used when writing an event to a log buffer. They take
+ * care of a bunch of stuff that can be repetitive and error-prone, such as
+ * acquiring/releasing the buffer lock, incrementing the event counter,
+ * expanding the log buffer, processing requests, etc. They also create a scope
+ * so that it's harder to leak the LogBuffer pointer, which can be problematic
+ * as the pointer is unstable when the buffer lock isn't acquired.
+ */
+
+#define ENTER_LOG(COUNTER, BUFFER, SIZE) \
+ do { \
+ MonoProfilerThread *thread__ = PROF_TLS_GET (); \
+ if (thread__->attached) \
+ buffer_lock (); \
+ g_assert (!thread__->busy && "Why are we trying to write a new event while already writing one?"); \
+ thread__->busy = TRUE; \
+ InterlockedIncrement ((COUNTER)); \
+ LogBuffer *BUFFER = ensure_logbuf_unsafe (thread__, (SIZE))
+
+#define EXIT_LOG_EXPLICIT(SEND, REQUESTS) \
+ thread__->busy = FALSE; \
+ if ((SEND)) \
+ send_log_unsafe (TRUE); \
+ if (thread__->attached) \
+ buffer_unlock (); \
+ if ((REQUESTS)) \
+ process_requests (); \
+ } while (0)
+
+// Pass these to EXIT_LOG_EXPLICIT () for easier reading.
+#define DO_SEND TRUE
+#define NO_SEND FALSE
+#define DO_REQUESTS TRUE
+#define NO_REQUESTS FALSE
+
+#define EXIT_LOG EXIT_LOG_EXPLICIT (DO_SEND, DO_REQUESTS)
+
+static volatile gint32 buffer_rwlock_count;
+static volatile gpointer buffer_rwlock_exclusive;
+
+// Can be used recursively.
+static void
+buffer_lock (void)
+{
+ /*
+ * If the thread holding the exclusive lock tries to modify the
+ * reader count, just make it a no-op. This way, we also avoid
+ * invoking the GC safe point macros below, which could break if
+ * done from a thread that is currently the initiator of STW.
+ *
+ * In other words, we rely on the fact that the GC thread takes
+ * the exclusive lock in the gc_event () callback when the world
+ * is about to stop.
+ */
+ if (InterlockedReadPointer (&buffer_rwlock_exclusive) != (gpointer) thread_id ()) {
+ MONO_ENTER_GC_SAFE;
+
+ while (InterlockedReadPointer (&buffer_rwlock_exclusive))
+ mono_thread_info_yield ();
+
+ InterlockedIncrement (&buffer_rwlock_count);
+
+ MONO_EXIT_GC_SAFE;
+ }
+
+ mono_memory_barrier ();
+}
+
+static void
+buffer_unlock (void)
+{
+ mono_memory_barrier ();
+
+ // See the comment in buffer_lock ().
+ if (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id ())
+ return;
+
+ g_assert (InterlockedRead (&buffer_rwlock_count) && "Why are we trying to decrement a zero reader count?");
+
+ InterlockedDecrement (&buffer_rwlock_count);
+}
+
+// Cannot be used recursively.
+static void
+buffer_lock_excl (void)
+{
+ gpointer tid = (gpointer) thread_id ();
+
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) != tid && "Why are we taking the exclusive lock twice?");
+
+ MONO_ENTER_GC_SAFE;
+
+ while (InterlockedCompareExchangePointer (&buffer_rwlock_exclusive, tid, 0))
+ mono_thread_info_yield ();
+
+ while (InterlockedRead (&buffer_rwlock_count))
+ mono_thread_info_yield ();
+
+ MONO_EXIT_GC_SAFE;
+
+ mono_memory_barrier ();
+}
+
+static void
+buffer_unlock_excl (void)
+{
+ mono_memory_barrier ();
+
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why is the exclusive lock not held?");
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why does another thread hold the exclusive lock?");
+ g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why are there readers when the exclusive lock is held?");
+
+ InterlockedWritePointer (&buffer_rwlock_exclusive, NULL);
+}
+
+typedef struct _BinaryObject BinaryObject;
+struct _BinaryObject {
+ BinaryObject *next;
+ void *addr;
+ char *name;
+};
+
+struct _MonoProfiler {
+ FILE* file;
+#if defined (HAVE_SYS_ZLIB)
+ gzFile gzfile;
+#endif
+ char *args;
+ uint64_t startup_time;
+ int pipe_output;
+ int command_port;
+ int server_socket;
+ int pipes [2];
+ MonoNativeThreadId helper_thread;
+ MonoNativeThreadId writer_thread;
+ MonoNativeThreadId dumper_thread;
+ volatile gint32 run_writer_thread;
+ MonoLockFreeAllocSizeClass writer_entry_size_class;
+ MonoLockFreeAllocator writer_entry_allocator;
+ MonoLockFreeQueue writer_queue;
+ MonoSemType writer_queue_sem;
+ MonoConcurrentHashTable *method_table;
+ mono_mutex_t method_table_mutex;
+ volatile gint32 run_dumper_thread;
+ MonoLockFreeQueue dumper_queue;
+ MonoSemType dumper_queue_sem;
+ MonoLockFreeAllocSizeClass sample_size_class;
+ MonoLockFreeAllocator sample_allocator;
+ MonoLockFreeQueue sample_reuse_queue;
+ BinaryObject *binary_objects;
+ GPtrArray *coverage_filters;
+};
+
+typedef struct {
+ MonoLockFreeQueueNode node;
+ GPtrArray *methods;
+ LogBuffer *buffer;
+} WriterQueueEntry;
+
+#define WRITER_ENTRY_BLOCK_SIZE (mono_pagesize ())
+
+typedef struct {
+ MonoMethod *method;
+ MonoJitInfo *ji;
+ uint64_t time;
+} MethodInfo;
+
+#ifdef HOST_WIN32
+
+#define PROF_TLS_SET(VAL) (TlsSetValue (profiler_tls, (VAL)))
+#define PROF_TLS_GET() ((MonoProfilerThread *) TlsGetValue (profiler_tls))
+#define PROF_TLS_INIT() (profiler_tls = TlsAlloc ())
+#define PROF_TLS_FREE() (TlsFree (profiler_tls))
+
+static DWORD profiler_tls;
+
+#elif HAVE_KW_THREAD
+
+#define PROF_TLS_SET(VAL) (profiler_tls = (VAL))
+#define PROF_TLS_GET() (profiler_tls)
+#define PROF_TLS_INIT()
+#define PROF_TLS_FREE()
+
+static __thread MonoProfilerThread *profiler_tls;
+
+#else
+
+#define PROF_TLS_SET(VAL) (pthread_setspecific (profiler_tls, (VAL)))
+#define PROF_TLS_GET() ((MonoProfilerThread *) pthread_getspecific (profiler_tls))
+#define PROF_TLS_INIT() (pthread_key_create (&profiler_tls, NULL))
+#define PROF_TLS_FREE() (pthread_key_delete (profiler_tls))
+
+static pthread_key_t profiler_tls;
+
+#endif
+
+static char*
+pstrdup (const char *s)
+{
+ int len = strlen (s) + 1;
+ char *p = (char *) g_malloc (len);
+ memcpy (p, s, len);
+ return p;
+}
+
+static void *
+alloc_buffer (int size)
+{
+ return mono_valloc (NULL, size, MONO_MMAP_READ | MONO_MMAP_WRITE | MONO_MMAP_ANON | MONO_MMAP_PRIVATE, MONO_MEM_ACCOUNT_PROFILER);
+}
+
+static void
+free_buffer (void *buf, int size)
+{
+ mono_vfree (buf, size, MONO_MEM_ACCOUNT_PROFILER);
+}
+
+static LogBuffer*
+create_buffer (uintptr_t tid)
+{
+ LogBuffer* buf = (LogBuffer *) alloc_buffer (BUFFER_SIZE);
+
+ InterlockedIncrement (&buffer_allocations_ctr);
+
+ buf->size = BUFFER_SIZE;
+ buf->time_base = current_time ();
+ buf->last_time = buf->time_base;
+ buf->buf_end = (unsigned char *) buf + buf->size;
+ buf->cursor = buf->buf;
+ buf->thread_id = tid;
+
+ return buf;
+}
+
+/*
+ * Must be called with the reader lock held if thread is the current thread, or
+ * the exclusive lock if thread is a different thread. However, if thread is
+ * the current thread, and init_thread () was called with add_to_lls = FALSE,
+ * then no locking is necessary.
+ */
+static void
+init_buffer_state (MonoProfilerThread *thread)
+{
+ thread->buffer = create_buffer (thread->node.key);
+ thread->methods = NULL;
+}
+
+static void
+clear_hazard_pointers (MonoThreadHazardPointers *hp)
+{
+ mono_hazard_pointer_clear (hp, 0);
+ mono_hazard_pointer_clear (hp, 1);
+ mono_hazard_pointer_clear (hp, 2);
+}
+
+static MonoProfilerThread *
+init_thread (MonoProfiler *prof, gboolean add_to_lls)
+{
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+
+ /*
+ * Sometimes we may try to initialize a thread twice. One example is the
+ * main thread: We initialize it when setting up the profiler, but we will
+ * also get a thread_start () callback for it. Another example is when
+ * attaching new threads to the runtime: We may get a gc_alloc () callback
+ * for that thread's thread object (where we initialize it), soon followed
+ * by a thread_start () callback.
+ *
+ * These cases are harmless anyhow. Just return if we've already done the
+ * initialization work.
+ */
+ if (thread)
+ return thread;
+
+ thread = g_malloc (sizeof (MonoProfilerThread));
+ thread->node.key = thread_id ();
+ thread->profiler = prof;
+ thread->attached = add_to_lls;
+ thread->call_depth = 0;
+ thread->busy = 0;
+ thread->ended = FALSE;
+
+ init_buffer_state (thread);
+
+ /*
+ * Some internal profiler threads don't need to be cleaned up
+ * by the main thread on shutdown.
+ */
+ if (add_to_lls) {
+ MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+ g_assert (mono_lls_insert (&profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
+ clear_hazard_pointers (hp);
+ }
+
+ PROF_TLS_SET (thread);
+
+ return thread;
+}
+
+// Only valid if init_thread () was called with add_to_lls = FALSE.
+static void
+deinit_thread (MonoProfilerThread *thread)
+{
+ g_assert (!thread->attached && "Why are we manually freeing an attached thread?");
+
+ g_free (thread);
+ PROF_TLS_SET (NULL);
+}
+
+// Only valid if init_thread () was called with add_to_lls = FALSE.
+static LogBuffer *
+ensure_logbuf_unsafe (MonoProfilerThread *thread, int bytes)
+{
+ LogBuffer *old = thread->buffer;
+
+ if (old && old->cursor + bytes + 100 < old->buf_end)
+ return old;
+
+ LogBuffer *new_ = create_buffer (thread->node.key);
+ new_->next = old;
+ thread->buffer = new_;
+
+ return new_;
+}
+
+static void
+encode_uleb128 (uint64_t value, uint8_t *buf, uint8_t **endbuf)
+{
+ uint8_t *p = buf;
+
+ do {
+ uint8_t b = value & 0x7f;
+ value >>= 7;
+
+ if (value != 0) /* more bytes to come */
+ b |= 0x80;
+
+ *p ++ = b;
+ } while (value);
+
+ *endbuf = p;
+}
+
+static void
+encode_sleb128 (intptr_t value, uint8_t *buf, uint8_t **endbuf)
+{
+ int more = 1;
+ int negative = (value < 0);
+ unsigned int size = sizeof (intptr_t) * 8;
+ uint8_t byte;
+ uint8_t *p = buf;
+
+ while (more) {
+ byte = value & 0x7f;
+ value >>= 7;
+
+ /* the following is unnecessary if the
+ * implementation of >>= uses an arithmetic rather
+ * than logical shift for a signed left operand
+ */
+ if (negative)
+ /* sign extend */
+ value |= - ((intptr_t) 1 <<(size - 7));
+
+ /* sign bit of byte is second high order bit (0x40) */
+ if ((value == 0 && !(byte & 0x40)) ||
+ (value == -1 && (byte & 0x40)))
+ more = 0;
+ else
+ byte |= 0x80;
+
+ *p ++= byte;
+ }
+
+ *endbuf = p;
+}
+
+static void
+emit_byte (LogBuffer *logbuffer, int value)
+{
+ logbuffer->cursor [0] = value;
+ logbuffer->cursor++;
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_value (LogBuffer *logbuffer, int value)
+{
+ encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_time (LogBuffer *logbuffer, uint64_t value)
+{
+ uint64_t tdiff = value - logbuffer->last_time;
+ encode_uleb128 (tdiff, logbuffer->cursor, &logbuffer->cursor);
+ logbuffer->last_time = value;
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_event_time (LogBuffer *logbuffer, int event, uint64_t time)
+{
+ emit_byte (logbuffer, event);
+ emit_time (logbuffer, time);
+}
+
+static void
+emit_event (LogBuffer *logbuffer, int event)
+{
+ emit_event_time (logbuffer, event, current_time ());
+}
+
+static void
+emit_svalue (LogBuffer *logbuffer, int64_t value)
+{
+ encode_sleb128 (value, logbuffer->cursor, &logbuffer->cursor);
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_uvalue (LogBuffer *logbuffer, uint64_t value)
+{
+ encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_ptr (LogBuffer *logbuffer, void *ptr)
+{
+ if (!logbuffer->ptr_base)
+ logbuffer->ptr_base = (uintptr_t) ptr;
+
+ emit_svalue (logbuffer, (intptr_t) ptr - logbuffer->ptr_base);
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_method_inner (LogBuffer *logbuffer, void *method)
+{
+ if (!logbuffer->method_base) {
+ logbuffer->method_base = (intptr_t) method;
+ logbuffer->last_method = (intptr_t) method;
+ }
+
+ encode_sleb128 ((intptr_t) ((char *) method - (char *) logbuffer->last_method), logbuffer->cursor, &logbuffer->cursor);
+ logbuffer->last_method = (intptr_t) method;
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+register_method_local (MonoMethod *method, MonoJitInfo *ji)
+{
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+
+ if (!mono_conc_hashtable_lookup (thread->profiler->method_table, method)) {
+ MethodInfo *info = (MethodInfo *) g_malloc (sizeof (MethodInfo));
+
+ info->method = method;
+ info->ji = ji;
+ info->time = current_time ();
+
+ GPtrArray *arr = thread->methods ? thread->methods : (thread->methods = g_ptr_array_new ());
+ g_ptr_array_add (arr, info);
+ }
+}
+
+static void
+emit_method (LogBuffer *logbuffer, MonoMethod *method)
+{
+ register_method_local (method, NULL);
+ emit_method_inner (logbuffer, method);
+}
+
+static void
+emit_obj (LogBuffer *logbuffer, void *ptr)
+{
+ if (!logbuffer->obj_base)
+ logbuffer->obj_base = (uintptr_t) ptr >> 3;
+
+ emit_svalue (logbuffer, ((uintptr_t) ptr >> 3) - logbuffer->obj_base);
+
+ g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
+}
+
+static void
+emit_string (LogBuffer *logbuffer, const char *str, size_t size)
+{
+ size_t i = 0;
+ if (str) {
+ for (; i < size; i++) {
+ if (str[i] == '\0')
+ break;
+ emit_byte (logbuffer, str [i]);
+ }
+ }
+ emit_byte (logbuffer, '\0');
+}
+
+static void
+emit_double (LogBuffer *logbuffer, double value)
+{
+ int i;
+ unsigned char buffer[8];
+ memcpy (buffer, &value, 8);
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ for (i = 7; i >= 0; i--)
+#else
+ for (i = 0; i < 8; i++)
+#endif
+ emit_byte (logbuffer, buffer[i]);
+}
+
+static char*
+write_int16 (char *buf, int32_t value)
+{
+ int i;
+ for (i = 0; i < 2; ++i) {
+ buf [i] = value;
+ value >>= 8;
+ }
+ return buf + 2;
+}
+
+static char*
+write_int32 (char *buf, int32_t value)
+{
+ int i;
+ for (i = 0; i < 4; ++i) {
+ buf [i] = value;
+ value >>= 8;
+ }
+ return buf + 4;
+}
+
+static char*
+write_int64 (char *buf, int64_t value)
+{
+ int i;
+ for (i = 0; i < 8; ++i) {
+ buf [i] = value;
+ value >>= 8;
+ }
+ return buf + 8;
+}
+
+static char *
+write_header_string (char *p, const char *str)
+{
+ size_t len = strlen (str) + 1;
+
+ p = write_int32 (p, len);
+ strcpy (p, str);
+
+ return p + len;
+}
+
+static void
+dump_header (MonoProfiler *profiler)
+{
+ const char *args = profiler->args;
+ const char *arch = mono_config_get_cpu ();
+ const char *os = mono_config_get_os ();
+
+ char *hbuf = g_malloc (
+ sizeof (gint32) /* header id */ +
+ sizeof (gint8) /* major version */ +
+ sizeof (gint8) /* minor version */ +
+ sizeof (gint8) /* data version */ +
+ sizeof (gint8) /* word size */ +
+ sizeof (gint64) /* startup time */ +
+ sizeof (gint32) /* timer overhead */ +
+ sizeof (gint32) /* flags */ +
+ sizeof (gint32) /* process id */ +
+ sizeof (gint16) /* command port */ +
+ sizeof (gint32) + strlen (args) + 1 /* arguments */ +
+ sizeof (gint32) + strlen (arch) + 1 /* architecture */ +
+ sizeof (gint32) + strlen (os) + 1 /* operating system */
+ );
+ char *p = hbuf;
+
+ p = write_int32 (p, LOG_HEADER_ID);
+ *p++ = LOG_VERSION_MAJOR;
+ *p++ = LOG_VERSION_MINOR;
+ *p++ = LOG_DATA_VERSION;
+ *p++ = sizeof (void *);
+ p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
+ p = write_int32 (p, timer_overhead);
+ p = write_int32 (p, 0); /* flags */
+ p = write_int32 (p, process_id ());
+ p = write_int16 (p, profiler->command_port);
+ p = write_header_string (p, args);
+ p = write_header_string (p, arch);
+ p = write_header_string (p, os);
+
+#if defined (HAVE_SYS_ZLIB)
+ if (profiler->gzfile) {
+ gzwrite (profiler->gzfile, hbuf, p - hbuf);
+ } else
+#endif
+ {
+ fwrite (hbuf, p - hbuf, 1, profiler->file);
+ fflush (profiler->file);
+ }
+
+ g_free (hbuf);
+}
+
+/*
+ * Must be called with the reader lock held if thread is the current thread, or
+ * the exclusive lock if thread is a different thread. However, if thread is
+ * the current thread, and init_thread () was called with add_to_lls = FALSE,
+ * then no locking is necessary.
+ */
+static void
+send_buffer (MonoProfilerThread *thread)
+{
+ WriterQueueEntry *entry = mono_lock_free_alloc (&thread->profiler->writer_entry_allocator);
+ entry->methods = thread->methods;
+ entry->buffer = thread->buffer;
+
+ mono_lock_free_queue_node_init (&entry->node, FALSE);
+
+ mono_lock_free_queue_enqueue (&thread->profiler->writer_queue, &entry->node);
+ mono_os_sem_post (&thread->profiler->writer_queue_sem);
+}
+
+static void
+free_thread (gpointer p)
+{
+ MonoProfilerThread *thread = p;
+
+ if (!thread->ended) {
+ /*
+ * The thread is being cleaned up by the main thread during
+ * shutdown. This typically happens for internal runtime
+ * threads. We need to synthesize a thread end event.
+ */
+
+ InterlockedIncrement (&thread_ends_ctr);
+
+ LogBuffer *buf = ensure_logbuf_unsafe (thread,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
+ );
+
+ emit_event (buf, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (buf, TYPE_THREAD);
+ emit_ptr (buf, (void *) thread->node.key);
+ }
+
+ send_buffer (thread);
+
+ g_free (thread);
+}
+
+static void
+remove_thread (MonoProfilerThread *thread)
+{
+ MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+
+ if (mono_lls_remove (&profiler_thread_list, hp, &thread->node))
+ mono_thread_hazardous_try_free (thread, free_thread);
+
+ clear_hazard_pointers (hp);
+}
+
+static void
+dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
+{
+ char hbuf [128];
+ char *p = hbuf;
+
+ if (buf->next)
+ dump_buffer (profiler, buf->next);
+
+ if (buf->cursor - buf->buf) {
+ p = write_int32 (p, BUF_ID);
+ p = write_int32 (p, buf->cursor - buf->buf);
+ p = write_int64 (p, buf->time_base);
+ p = write_int64 (p, buf->ptr_base);
+ p = write_int64 (p, buf->obj_base);
+ p = write_int64 (p, buf->thread_id);
+ p = write_int64 (p, buf->method_base);
+
+#if defined (HAVE_SYS_ZLIB)
+ if (profiler->gzfile) {
+ gzwrite (profiler->gzfile, hbuf, p - hbuf);
+ gzwrite (profiler->gzfile, buf->buf, buf->cursor - buf->buf);
+ } else
+#endif
+ {
+ fwrite (hbuf, p - hbuf, 1, profiler->file);
+ fwrite (buf->buf, buf->cursor - buf->buf, 1, profiler->file);
+ fflush (profiler->file);
+ }
+ }
+
+ free_buffer (buf, buf->size);
+}
+
+static void
+dump_buffer_threadless (MonoProfiler *profiler, LogBuffer *buf)
+{
+ for (LogBuffer *iter = buf; iter; iter = iter->next)
+ iter->thread_id = 0;
+
+ dump_buffer (profiler, buf);
+}
+
+static void
+process_requests (void)
+{
+ if (heapshot_requested)
+ mono_gc_collect (mono_gc_max_generation ());
+}
+
+// Only valid if init_thread () was called with add_to_lls = FALSE.
+static void
+send_log_unsafe (gboolean if_needed)
+{
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+
+ if (!if_needed || (if_needed && thread->buffer->next)) {
+ if (!thread->attached)
+ for (LogBuffer *iter = thread->buffer; iter; iter = iter->next)
+ iter->thread_id = 0;
+
+ send_buffer (thread);
+ init_buffer_state (thread);
+ }
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point_flush (void)
+{
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
+
+ MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+ g_assert (thread->attached && "Why is a thread in the LLS not attached?");
+
+ send_buffer (thread);
+ init_buffer_state (thread);
+ } MONO_LLS_FOREACH_SAFE_END
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point_mark (MonoProfilerSyncPointType type)
+{
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
+
+ ENTER_LOG (&sync_points_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* type */
+ );
+
+ emit_event (logbuffer, TYPE_META | TYPE_SYNC_POINT);
+ emit_byte (logbuffer, type);
+
+ EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
+
+ send_log_unsafe (FALSE);
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point (MonoProfilerSyncPointType type)
+{
+ sync_point_flush ();
+ sync_point_mark (type);
+}
+
+static int
+gc_reference (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num, MonoObject **refs, uintptr_t *offsets, void *data)
+{
+ /* account for object alignment in the heap */
+ size += 7;
+ size &= ~7;
+
+ ENTER_LOG (&heap_objects_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* obj */ +
+ LEB128_SIZE /* klass */ +
+ LEB128_SIZE /* size */ +
+ LEB128_SIZE /* num */ +
+ num * (
+ LEB128_SIZE /* offset */ +
+ LEB128_SIZE /* ref */
+ )
+ );
+
+ emit_event (logbuffer, TYPE_HEAP_OBJECT | TYPE_HEAP);
+ emit_obj (logbuffer, obj);
+ emit_ptr (logbuffer, klass);
+ emit_value (logbuffer, size);
+ emit_value (logbuffer, num);
+
+ uintptr_t last_offset = 0;
+
+ for (int i = 0; i < num; ++i) {
+ emit_value (logbuffer, offsets [i] - last_offset);
+ last_offset = offsets [i];
+ emit_obj (logbuffer, refs [i]);
+ }
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ return 0;
+}
+
+static unsigned int hs_mode_ms = 0;
+static unsigned int hs_mode_gc = 0;
+static unsigned int hs_mode_ondemand = 0;
+static unsigned int gc_count = 0;
+static uint64_t last_hs_time = 0;
+static gboolean do_heap_walk = FALSE;
+
+static void
+heap_walk (MonoProfiler *profiler)
+{
+ ENTER_LOG (&heap_starts_ctr, logbuffer,
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ mono_gc_walk_heap (0, gc_reference, NULL);
+
+ ENTER_LOG (&heap_ends_ctr, logbuffer,
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+static void
+gc_roots (MonoProfiler *prof, int num, void **objects, int *root_types, uintptr_t *extra_info)
+{
+ ENTER_LOG (&heap_roots_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* num */ +
+ LEB128_SIZE /* collections */ +
+ num * (
+ LEB128_SIZE /* object */ +
+ LEB128_SIZE /* root type */ +
+ LEB128_SIZE /* extra info */
+ )
+ );
+
+ emit_event (logbuffer, TYPE_HEAP_ROOT | TYPE_HEAP);
+ emit_value (logbuffer, num);
+ emit_value (logbuffer, mono_gc_collection_count (mono_gc_max_generation ()));
+
+ for (int i = 0; i < num; ++i) {
+ emit_obj (logbuffer, objects [i]);
+ emit_byte (logbuffer, root_types [i]);
+ emit_value (logbuffer, extra_info [i]);
+ }
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+static void
+gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
+{
+ ENTER_LOG (&gc_events_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* gc event */ +
+ BYTE_SIZE /* generation */
+ );
+
+ emit_event (logbuffer, TYPE_GC_EVENT | TYPE_GC);
+ emit_byte (logbuffer, ev);
+ emit_byte (logbuffer, generation);
+
+ EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
+
+ switch (ev) {
+ case MONO_GC_EVENT_START:
+ if (generation == mono_gc_max_generation ())
+ gc_count++;
+
+ uint64_t now = current_time ();
+
+ if (hs_mode_ms && (now - last_hs_time) / 1000 * 1000 >= hs_mode_ms)
+ do_heap_walk = TRUE;
+ else if (hs_mode_gc && !(gc_count % hs_mode_gc))
+ do_heap_walk = TRUE;
+ else if (hs_mode_ondemand)
+ do_heap_walk = heapshot_requested;
+ else if (!hs_mode_ms && !hs_mode_gc && generation == mono_gc_max_generation ())
+ do_heap_walk = TRUE;
+ break;
+ case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
+ /*
+ * Ensure that no thread can be in the middle of writing to
+ * a buffer when the world stops...
+ */
+ buffer_lock_excl ();
+ break;
+ case MONO_GC_EVENT_POST_STOP_WORLD:
+ /*
+ * ... So that we now have a consistent view of all buffers.
+ * This allows us to flush them. We need to do this because
+ * they may contain object allocation events that need to be
+ * committed to the log file before any object move events
+ * that will be produced during this GC.
+ */
+ sync_point (SYNC_POINT_WORLD_STOP);
+ break;
+ case MONO_GC_EVENT_PRE_START_WORLD:
+ if (do_heap_shot && do_heap_walk) {
+ heap_walk (profiler);
+
+ do_heap_walk = FALSE;
+ heapshot_requested = 0;
+ last_hs_time = current_time ();
+ }
+ break;
+ case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
+ /*
+ * Similarly, we must now make sure that any object moves
+ * written to the GC thread's buffer are flushed. Otherwise,
+ * object allocation events for certain addresses could come
+ * after the move events that made those addresses available.
+ */
+ sync_point_mark (SYNC_POINT_WORLD_START);
+
+ /*
+ * Finally, it is safe to allow other threads to write to
+ * their buffers again.
+ */
+ buffer_unlock_excl ();
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gc_resize (MonoProfiler *profiler, int64_t new_size)
+{
+ ENTER_LOG (&gc_resizes_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* new size */
+ );
+
+ emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
+ emit_value (logbuffer, new_size);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+typedef struct {
+ int count;
+ MonoMethod* methods [MAX_FRAMES];
+ int32_t il_offsets [MAX_FRAMES];
+ int32_t native_offsets [MAX_FRAMES];
+} FrameData;
+
+static int num_frames = MAX_FRAMES;
+
+static mono_bool
+walk_stack (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
+{
+ FrameData *frame = (FrameData *)data;
+ if (method && frame->count < num_frames) {
+ frame->il_offsets [frame->count] = il_offset;
+ frame->native_offsets [frame->count] = native_offset;
+ frame->methods [frame->count++] = method;
+ //printf ("In %d %s at %d (native: %d)\n", frame->count, mono_method_get_name (method), il_offset, native_offset);
+ }
+ return frame->count == num_frames;
+}
+
+/*
+ * a note about stack walks: they can cause more profiler events to fire,
+ * so we need to make sure they don't happen after we started emitting an
+ * event, hence the collect_bt/emit_bt split.
+ */
+static void
+collect_bt (FrameData *data)
+{
+ data->count = 0;
+ mono_stack_walk_no_il (walk_stack, data);
+}
+
+static void
+emit_bt (MonoProfiler *prof, LogBuffer *logbuffer, FrameData *data)
+{
+ /* FIXME: this is actually tons of data and we should
+ * just output it the first time and use an id the next
+ */
+ if (data->count > num_frames)
+ printf ("bad num frames: %d\n", data->count);
+ emit_value (logbuffer, data->count);
+ //if (*p != data.count) {
+ // printf ("bad num frames enc at %d: %d -> %d\n", count, data.count, *p); printf ("frames end: %p->%p\n", p, logbuffer->cursor); exit(0);}
+ while (data->count) {
+ emit_method (logbuffer, data->methods [--data->count]);
+ }
+}
+
+static void
+gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+{
+ init_thread (prof, TRUE);
+
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_ALLOC_BT : 0;
+ FrameData data;
+ uintptr_t len = mono_object_get_size (obj);
+ /* account for object alignment in the heap */
+ len += 7;
+ len &= ~7;
+
+ if (do_bt)
+ collect_bt (&data);
+
+ ENTER_LOG (&gc_allocs_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* klass */ +
+ LEB128_SIZE /* obj */ +
+ LEB128_SIZE /* size */ +
+ (do_bt ? (
+ LEB128_SIZE /* count */ +
+ data.count * (
+ LEB128_SIZE /* method */
+ )
+ ) : 0)
+ );
+
+ emit_event (logbuffer, do_bt | TYPE_ALLOC);
+ emit_ptr (logbuffer, klass);
+ emit_obj (logbuffer, obj);
+ emit_value (logbuffer, len);
+
+ if (do_bt)
+ emit_bt (prof, logbuffer, &data);
+
+ EXIT_LOG;
+}
+
+static void
+gc_moves (MonoProfiler *prof, void **objects, int num)
+{
+ ENTER_LOG (&gc_moves_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* num */ +
+ num * (
+ LEB128_SIZE /* object */
+ )
+ );
+
+ emit_event (logbuffer, TYPE_GC_MOVE | TYPE_GC);
+ emit_value (logbuffer, num);
+
+ for (int i = 0; i < num; ++i)
+ emit_obj (logbuffer, objects [i]);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+static void
+gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj)
+{
+ int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
+ FrameData data;
+
+ if (do_bt)
+ collect_bt (&data);
+
+ gint32 *ctr = op == MONO_PROFILER_GC_HANDLE_CREATED ? &gc_handle_creations_ctr : &gc_handle_deletions_ctr;
+
+ ENTER_LOG (ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* type */ +
+ LEB128_SIZE /* handle */ +
+ (op == MONO_PROFILER_GC_HANDLE_CREATED ? (
+ LEB128_SIZE /* obj */
+ ) : 0) +
+ (do_bt ? (
+ LEB128_SIZE /* count */ +
+ data.count * (
+ LEB128_SIZE /* method */
+ )
+ ) : 0)
+ );
+
+ if (op == MONO_PROFILER_GC_HANDLE_CREATED)
+ emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
+ else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
+ emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
+ else
+ g_assert_not_reached ();
+
+ emit_value (logbuffer, type);
+ emit_value (logbuffer, handle);
+
+ if (op == MONO_PROFILER_GC_HANDLE_CREATED)
+ emit_obj (logbuffer, obj);
+
+ if (do_bt)
+ emit_bt (prof, logbuffer, &data);
+
+ EXIT_LOG;
+}
+
+static void
+finalize_begin (MonoProfiler *prof)
+{
+ ENTER_LOG (&finalize_begins_ctr, buf,
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_START | TYPE_GC);
+
+ EXIT_LOG;
+}
+
+static void
+finalize_end (MonoProfiler *prof)
+{
+ ENTER_LOG (&finalize_ends_ctr, buf,
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_END | TYPE_GC);
+
+ EXIT_LOG;
+}
+
+static void
+finalize_object_begin (MonoProfiler *prof, MonoObject *obj)
+{
+ ENTER_LOG (&finalize_object_begins_ctr, buf,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* obj */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_OBJECT_START | TYPE_GC);
+ emit_obj (buf, obj);
+
+ EXIT_LOG;
+}
+
+static void
+finalize_object_end (MonoProfiler *prof, MonoObject *obj)
+{
+ ENTER_LOG (&finalize_object_ends_ctr, buf,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* obj */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_OBJECT_END | TYPE_GC);
+ emit_obj (buf, obj);
+
+ EXIT_LOG;
+}
+
+static char*
+push_nesting (char *p, MonoClass *klass)
+{
+ MonoClass *nesting;
+ const char *name;
+ const char *nspace;
+ nesting = mono_class_get_nesting_type (klass);
+ if (nesting) {
+ p = push_nesting (p, nesting);
+ *p++ = '/';
+ *p = 0;
+ }
+ name = mono_class_get_name (klass);
+ nspace = mono_class_get_namespace (klass);
+ if (*nspace) {
+ strcpy (p, nspace);
+ p += strlen (nspace);
+ *p++ = '.';
+ *p = 0;
+ }
+ strcpy (p, name);
+ p += strlen (name);
+ return p;
+}
+
+static char*
+type_name (MonoClass *klass)
+{
+ char buf [1024];
+ char *p;
+ push_nesting (buf, klass);
+ p = (char *) g_malloc (strlen (buf) + 1);
+ strcpy (p, buf);
+ return p;
+}
+
+static void
+image_loaded (MonoProfiler *prof, MonoImage *image, int result)
+{
+ if (result != MONO_PROFILE_OK)
+ return;
+
+ const char *name = mono_image_get_filename (image);
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG (&image_loads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* image */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_IMAGE);
+ emit_ptr (logbuffer, image);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+}
+
+static void
+image_unloaded (MonoProfiler *prof, MonoImage *image)
+{
+ const char *name = mono_image_get_filename (image);
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG (&image_unloads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* image */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_IMAGE);
+ emit_ptr (logbuffer, image);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+}
+
+static void
+assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly, int result)
+{
+ if (result != MONO_PROFILE_OK)
+ return;
+
+ char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG (&assembly_loads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* assembly */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_ASSEMBLY);
+ emit_ptr (logbuffer, assembly);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+
+ mono_free (name);
+}
+
+static void
+assembly_unloaded (MonoProfiler *prof, MonoAssembly *assembly)
+{
+ char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG (&assembly_unloads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* assembly */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_ASSEMBLY);
+ emit_ptr (logbuffer, assembly);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+
+ mono_free (name);
+}
+
+static void
+class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
+{
+ if (result != MONO_PROFILE_OK)
+ return;
+
+ char *name;
+
+ if (InterlockedRead (&runtime_inited))
+ name = mono_type_get_name (mono_class_get_type (klass));
+ else
+ name = type_name (klass);
+
+ int nlen = strlen (name) + 1;
+ MonoImage *image = mono_class_get_image (klass);
+
+ ENTER_LOG (&class_loads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* klass */ +
+ LEB128_SIZE /* image */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_CLASS);
+ emit_ptr (logbuffer, klass);
+ emit_ptr (logbuffer, image);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+
+ if (runtime_inited)
+ mono_free (name);
+ else
+ g_free (name);
+}
+
+static void
+class_unloaded (MonoProfiler *prof, MonoClass *klass)
+{
+ char *name;
+
+ if (InterlockedRead (&runtime_inited))
+ name = mono_type_get_name (mono_class_get_type (klass));
+ else
+ name = type_name (klass);
+
+ int nlen = strlen (name) + 1;
+ MonoImage *image = mono_class_get_image (klass);
+
+ ENTER_LOG (&class_unloads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* klass */ +
+ LEB128_SIZE /* image */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_CLASS);
+ emit_ptr (logbuffer, klass);
+ emit_ptr (logbuffer, image);
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+
+ if (runtime_inited)
+ mono_free (name);
+ else
+ g_free (name);
+}
+
+static void process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method);
+
+static void
+method_enter (MonoProfiler *prof, MonoMethod *method)
+{
+ process_method_enter_coverage (prof, method);
+
+ if (!only_coverage && PROF_TLS_GET ()->call_depth++ <= max_call_depth) {
+ ENTER_LOG (&method_entries_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_ENTER | TYPE_METHOD);
+ emit_method (logbuffer, method);
+
+ EXIT_LOG;
+ }
+}
+
+static void
+method_leave (MonoProfiler *prof, MonoMethod *method)
+{
+ if (!only_coverage && --PROF_TLS_GET ()->call_depth <= max_call_depth) {
+ ENTER_LOG (&method_exits_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_LEAVE | TYPE_METHOD);
+ emit_method (logbuffer, method);
+
+ EXIT_LOG;
+ }
+}
+
+static void
+method_exc_leave (MonoProfiler *prof, MonoMethod *method)
+{
+ if (!only_coverage && !nocalls && --PROF_TLS_GET ()->call_depth <= max_call_depth) {
+ ENTER_LOG (&method_exception_exits_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
+ emit_method (logbuffer, method);
+
+ EXIT_LOG;
+ }
+}
+
+static void
+method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji, int result)
+{
+ if (result != MONO_PROFILE_OK)
+ return;
+
+ register_method_local (method, ji);
+
+ process_requests ();
+}
+
+static void
+code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
+{
+ char *name;
+ int nlen;
+
+ if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
+ name = (char *) data;
+ nlen = strlen (name) + 1;
+ } else {
+ name = NULL;
+ nlen = 0;
+ }
+
+ ENTER_LOG (&code_buffers_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* buffer */ +
+ LEB128_SIZE /* size */ +
+ (name ? (
+ nlen /* name */
+ ) : 0)
+ );
+
+ emit_event (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
+ emit_byte (logbuffer, type);
+ emit_ptr (logbuffer, buffer);
+ emit_value (logbuffer, size);
+
+ if (name) {
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+ }
+
+ EXIT_LOG;
+}
+
+static void
+throw_exc (MonoProfiler *prof, MonoObject *object)
+{
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_THROW_BT : 0;
+ FrameData data;
+
+ if (do_bt)
+ collect_bt (&data);
+
+ ENTER_LOG (&exception_throws_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* object */ +
+ (do_bt ? (
+ LEB128_SIZE /* count */ +
+ data.count * (
+ LEB128_SIZE /* method */
+ )
+ ) : 0)
+ );
+
+ emit_event (logbuffer, do_bt | TYPE_EXCEPTION);
+ emit_obj (logbuffer, object);
+
+ if (do_bt)
+ emit_bt (prof, logbuffer, &data);
+
+ EXIT_LOG;
+}
+
+static void
+clause_exc (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num)
+{
+ ENTER_LOG (&exception_clauses_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* clause type */ +
+ LEB128_SIZE /* clause num */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
+ emit_byte (logbuffer, clause_type);
+ emit_value (logbuffer, clause_num);
+ emit_method (logbuffer, method);
+
+ EXIT_LOG;
+}
+
+static void
+monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent event)
+{
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces && event == MONO_PROFILER_MONITOR_CONTENTION) ? TYPE_MONITOR_BT : 0;
+ FrameData data;
+
+ if (do_bt)
+ collect_bt (&data);
+
+ gint32 *ctr;
+
+ switch (event) {
+ case MONO_PROFILER_MONITOR_CONTENTION:
+ ctr = &monitor_contentions_ctr;
+ break;
+ case MONO_PROFILER_MONITOR_DONE:
+ ctr = &monitor_acquisitions_ctr;
+ break;
+ case MONO_PROFILER_MONITOR_FAIL:
+ ctr = &monitor_failures_ctr;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ ENTER_LOG (ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* object */ +
+ (do_bt ? (
+ LEB128_SIZE /* count */ +
+ data.count * (
+ LEB128_SIZE /* method */
+ )
+ ) : 0)
+ );
+
+ emit_event (logbuffer, (event << 4) | do_bt | TYPE_MONITOR);
+ emit_obj (logbuffer, object);
+
+ if (do_bt)
+ emit_bt (profiler, logbuffer, &data);
+
+ EXIT_LOG;
+}
+
+static void
+thread_start (MonoProfiler *prof, uintptr_t tid)
+{
+ init_thread (prof, TRUE);
+
+ ENTER_LOG (&thread_starts_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_THREAD);
+ emit_ptr (logbuffer, (void*) tid);
+
+ EXIT_LOG;
+}
+
+static void
+thread_end (MonoProfiler *prof, uintptr_t tid)
+{
+ ENTER_LOG (&thread_ends_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_THREAD);
+ emit_ptr (logbuffer, (void*) tid);
+
+ EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
+
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+
+ thread->ended = TRUE;
+ remove_thread (thread);
+
+ PROF_TLS_SET (NULL);
+}
+
+static void
+thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
+{
+ int len = strlen (name) + 1;
+
+ ENTER_LOG (&thread_names_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */ +
+ len /* name */
+ );
+
+ emit_event (logbuffer, TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_THREAD);
+ emit_ptr (logbuffer, (void*)tid);
+ memcpy (logbuffer->cursor, name, len);
+ logbuffer->cursor += len;
+
+ EXIT_LOG;
+}
+
+static void
+domain_loaded (MonoProfiler *prof, MonoDomain *domain, int result)
+{
+ if (result != MONO_PROFILE_OK)
+ return;
+
+ ENTER_LOG (&domain_loads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* domain id */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_DOMAIN);
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
+
+ EXIT_LOG;
+}
+
+static void
+domain_unloaded (MonoProfiler *prof, MonoDomain *domain)
+{
+ ENTER_LOG (&domain_unloads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* domain id */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_DOMAIN);
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
+
+ EXIT_LOG;
+}
+
+static void
+domain_name (MonoProfiler *prof, MonoDomain *domain, const char *name)
+{
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG (&domain_names_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* domain id */ +
+ nlen /* name */
+ );
+
+ emit_event (logbuffer, TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_DOMAIN);
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG;
+}
+
+static void
+context_loaded (MonoProfiler *prof, MonoAppContext *context)
+{
+ ENTER_LOG (&context_loads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* context id */ +
+ LEB128_SIZE /* domain id */
+ );
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_CONTEXT);
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
+
+ EXIT_LOG;
+}
+
+static void
+context_unloaded (MonoProfiler *prof, MonoAppContext *context)
+{
+ ENTER_LOG (&context_unloads_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* context id */ +
+ LEB128_SIZE /* domain id */
+ );
+
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_CONTEXT);
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
+ emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
+
+ EXIT_LOG;
+}
+
+typedef struct {
+ MonoMethod *method;
+ MonoDomain *domain;
+ void *base_address;
+ int offset;
+} AsyncFrameInfo;
+
+typedef struct {
+ MonoLockFreeQueueNode node;
+ MonoProfiler *prof;
+ uint64_t time;
+ uintptr_t tid;
+ void *ip;
+ int count;
+ AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
+} SampleHit;
+
+static mono_bool
+async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void *data)
+{
+ SampleHit *sample = (SampleHit *) data;
+
+ if (sample->count < num_frames) {
+ int i = sample->count;
+
+ sample->frames [i].method = method;
+ sample->frames [i].domain = domain;
+ sample->frames [i].base_address = base_address;
+ sample->frames [i].offset = offset;
+
+ sample->count++;
+ }
+
+ return sample->count == num_frames;
+}
+
+#define SAMPLE_SLOT_SIZE(FRAMES) (sizeof (SampleHit) + sizeof (AsyncFrameInfo) * (FRAMES - MONO_ZERO_LEN_ARRAY))
+#define SAMPLE_BLOCK_SIZE (mono_pagesize ())
+
+static void
+enqueue_sample_hit (gpointer p)
+{
+ SampleHit *sample = p;
+
+ mono_lock_free_queue_node_unpoison (&sample->node);
+ mono_lock_free_queue_enqueue (&sample->prof->dumper_queue, &sample->node);
+ mono_os_sem_post (&sample->prof->dumper_queue_sem);
+}
+
+static void
+mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
+{
+ /*
+ * Please note: We rely on the runtime loading the profiler with
+ * MONO_DL_EAGER (RTLD_NOW) so that references to runtime functions within
+ * this function (and its siblings) are resolved when the profiler is
+ * loaded. Otherwise, we would potentially invoke the dynamic linker when
+ * invoking runtime functions, which is not async-signal-safe.
+ */
+
+ if (InterlockedRead (&in_shutdown))
+ return;
+
+ SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
+
+ if (!sample) {
+ /*
+ * If we're out of reusable sample events and we're not allowed to
+ * allocate more, we have no choice but to drop the event.
+ */
+ if (InterlockedRead (&sample_allocations_ctr) >= max_allocated_sample_hits)
+ return;
+
+ sample = mono_lock_free_alloc (&profiler->sample_allocator);
+ sample->prof = profiler;
+ mono_lock_free_queue_node_init (&sample->node, TRUE);
+
+ InterlockedIncrement (&sample_allocations_ctr);
+ }
+
+ sample->count = 0;
+ mono_stack_walk_async_safe (&async_walk_stack, context, sample);
+
+ sample->time = current_time ();
+ sample->tid = thread_id ();
+ sample->ip = ip;
+
+ mono_thread_hazardous_try_free (sample, enqueue_sample_hit);
+}
+
+static uintptr_t *code_pages = 0;
+static int num_code_pages = 0;
+static int size_code_pages = 0;
+#define CPAGE_SHIFT (9)
+#define CPAGE_SIZE (1 << CPAGE_SHIFT)
+#define CPAGE_MASK (~(CPAGE_SIZE - 1))
+#define CPAGE_ADDR(p) ((p) & CPAGE_MASK)
+
+static uintptr_t
+add_code_page (uintptr_t *hash, uintptr_t hsize, uintptr_t page)
+{
+ uintptr_t i;
+ uintptr_t start_pos;
+ start_pos = (page >> CPAGE_SHIFT) % hsize;
+ i = start_pos;
+ do {
+ if (hash [i] && CPAGE_ADDR (hash [i]) == CPAGE_ADDR (page)) {
+ return 0;
+ } else if (!hash [i]) {
+ hash [i] = page;
+ return 1;
+ }
+ /* wrap around */
+ if (++i == hsize)
+ i = 0;
+ } while (i != start_pos);
+ /* should not happen */
+ printf ("failed code page store\n");
+ return 0;
+}
+
+static void
+add_code_pointer (uintptr_t ip)
+{
+ uintptr_t i;
+ if (num_code_pages * 2 >= size_code_pages) {
+ uintptr_t *n;
+ uintptr_t old_size = size_code_pages;
+ size_code_pages *= 2;
+ if (size_code_pages == 0)
+ size_code_pages = 16;
+ n = (uintptr_t *) g_calloc (sizeof (uintptr_t) * size_code_pages, 1);
+ for (i = 0; i < old_size; ++i) {
+ if (code_pages [i])
+ add_code_page (n, size_code_pages, code_pages [i]);
+ }
+ if (code_pages)
+ g_free (code_pages);
+ code_pages = n;
+ }
+ num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
+}
+
+/* ELF code crashes on some systems. */
+//#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
+#if 0
+static void
+dump_ubin (MonoProfiler *prof, const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
+{
+ int len = strlen (filename) + 1;
+
+ ENTER_LOG (&sample_ubins_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* load address */ +
+ LEB128_SIZE /* offset */ +
+ LEB128_SIZE /* size */ +
+ nlen /* file name */
+ );
+
+ emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
+ emit_svalue (logbuffer, load_addr);
+ emit_uvalue (logbuffer, offset);
+ emit_uvalue (logbuffer, size);
+ memcpy (logbuffer->cursor, filename, len);
+ logbuffer->cursor += len;
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+#endif
+
+static void
+dump_usym (MonoProfiler *prof, const char *name, uintptr_t value, uintptr_t size)
+{
+ int len = strlen (name) + 1;
+
+ ENTER_LOG (&sample_usyms_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* value */ +
+ LEB128_SIZE /* size */ +
+ len /* name */
+ );
+
+ emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
+ emit_ptr (logbuffer, (void*)value);
+ emit_value (logbuffer, size);
+ memcpy (logbuffer->cursor, name, len);
+ logbuffer->cursor += len;
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+/* ELF code crashes on some systems. */
+//#if defined(ELFMAG0)
+#if 0
+
+#if SIZEOF_VOID_P == 4
+#define ELF_WSIZE 32
+#else
+#define ELF_WSIZE 64
+#endif
+#ifndef ElfW
+#define ElfW(type) _ElfW (Elf, ELF_WSIZE, type)
+#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t) e##w##t
+#endif
+
+static void
+dump_elf_symbols (MonoProfiler *prof, ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
+{
+ int i;
+ for (i = 0; i < num_symbols; ++i) {
+ const char* sym;
+ sym = strtab + symbols [i].st_name;
+ if (!symbols [i].st_name || !symbols [i].st_size || (symbols [i].st_info & 0xf) != STT_FUNC)
+ continue;
+ //printf ("symbol %s at %d\n", sym, symbols [i].st_value);
+ dump_usym (sym, (uintptr_t)load_addr + symbols [i].st_value, symbols [i].st_size);
+ }
+}
+
+static int
+read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
+{
+ int fd, i;
+ void *data;
+ struct stat statb;
+ uint64_t file_size;
+ ElfW(Ehdr) *header;
+ ElfW(Shdr) *sheader;
+ ElfW(Shdr) *shstrtabh;
+ ElfW(Shdr) *symtabh = NULL;
+ ElfW(Shdr) *strtabh = NULL;
+ ElfW(Sym) *symbols = NULL;
+ const char *strtab;
+ int num_symbols;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ if (fstat (fd, &statb) != 0) {
+ close (fd);
+ return 0;
+ }
+ file_size = statb.st_size;
+ data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close (fd);
+ if (data == MAP_FAILED)
+ return 0;
+ header = data;
+ if (header->e_ident [EI_MAG0] != ELFMAG0 ||
+ header->e_ident [EI_MAG1] != ELFMAG1 ||
+ header->e_ident [EI_MAG2] != ELFMAG2 ||
+ header->e_ident [EI_MAG3] != ELFMAG3 ) {
+ munmap (data, file_size);
+ return 0;
+ }
+ sheader = (void*)((char*)data + header->e_shoff);
+ shstrtabh = (void*)((char*)sheader + (header->e_shentsize * header->e_shstrndx));
+ strtab = (const char*)data + shstrtabh->sh_offset;
+ for (i = 0; i < header->e_shnum; ++i) {
+ //printf ("section header: %d\n", sheader->sh_type);
+ if (sheader->sh_type == SHT_SYMTAB) {
+ symtabh = sheader;
+ strtabh = (void*)((char*)data + header->e_shoff + sheader->sh_link * header->e_shentsize);
+ /*printf ("symtab section header: %d, .strstr: %d\n", i, sheader->sh_link);*/
+ break;
+ }
+ sheader = (void*)((char*)sheader + header->e_shentsize);
+ }
+ if (!symtabh || !strtabh) {
+ munmap (data, file_size);
+ return 0;
+ }
+ strtab = (const char*)data + strtabh->sh_offset;
+ num_symbols = symtabh->sh_size / symtabh->sh_entsize;
+ symbols = (void*)((char*)data + symtabh->sh_offset);
+ dump_elf_symbols (symbols, num_symbols, strtab, load_addr);
+ munmap (data, file_size);
+ return 1;
+}
+#endif
+
+/* ELF code crashes on some systems. */
+//#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
+#if 0
+static int
+elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
+{
+ MonoProfiler *prof = data;
+ char buf [256];
+ const char *filename;
+ BinaryObject *obj;
+ char *a = (void*)info->dlpi_addr;
+ int i, num_sym;
+ ElfW(Dyn) *dyn = NULL;
+ ElfW(Sym) *symtab = NULL;
+ ElfW(Word) *hash_table = NULL;
+ ElfW(Ehdr) *header = NULL;
+ const char* strtab = NULL;
+ for (obj = prof->binary_objects; obj; obj = obj->next) {
+ if (obj->addr == a)
+ return 0;
+ }
+ filename = info->dlpi_name;
+ if (!filename)
+ return 0;
+ if (!info->dlpi_addr && !filename [0]) {
+ int l = readlink ("/proc/self/exe", buf, sizeof (buf) - 1);
+ if (l > 0) {
+ buf [l] = 0;
+ filename = buf;
+ }
+ }
+ obj = g_calloc (sizeof (BinaryObject), 1);
+ obj->addr = (void*)info->dlpi_addr;
+ obj->name = pstrdup (filename);
+ obj->next = prof->binary_objects;
+ prof->binary_objects = obj;
+ //printf ("loaded file: %s at %p, segments: %d\n", filename, (void*)info->dlpi_addr, info->dlpi_phnum);
+ a = NULL;
+ for (i = 0; i < info->dlpi_phnum; ++i) {
+ //printf ("segment type %d file offset: %d, size: %d\n", info->dlpi_phdr[i].p_type, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
+ if (info->dlpi_phdr[i].p_type == PT_LOAD && !header) {
+ header = (ElfW(Ehdr)*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+ if (header->e_ident [EI_MAG0] != ELFMAG0 ||
+ header->e_ident [EI_MAG1] != ELFMAG1 ||
+ header->e_ident [EI_MAG2] != ELFMAG2 ||
+ header->e_ident [EI_MAG3] != ELFMAG3 ) {
+ header = NULL;
+ }
+ dump_ubin (prof, filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
+ } else if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
+ dyn = (ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+ }
+ }
+ if (read_elf_symbols (prof, filename, (void*)info->dlpi_addr))
+ return 0;
+ if (!info->dlpi_name || !info->dlpi_name[0])
+ return 0;
+ if (!dyn)
+ return 0;
+ for (i = 0; dyn [i].d_tag != DT_NULL; ++i) {
+ if (dyn [i].d_tag == DT_SYMTAB) {
+ if (symtab && do_debug)
+ printf ("multiple symtabs: %d\n", i);
+ symtab = (ElfW(Sym) *)(a + dyn [i].d_un.d_ptr);
+ } else if (dyn [i].d_tag == DT_HASH) {
+ hash_table = (ElfW(Word) *)(a + dyn [i].d_un.d_ptr);
+ } else if (dyn [i].d_tag == DT_STRTAB) {
+ strtab = (const char*)(a + dyn [i].d_un.d_ptr);
+ }
+ }
+ if (!hash_table)
+ return 0;
+ num_sym = hash_table [1];
+ dump_elf_symbols (prof, symtab, num_sym, strtab, (void*)info->dlpi_addr);
+ return 0;
+}
+
+static int
+load_binaries (MonoProfiler *prof)
+{
+ dl_iterate_phdr (elf_dl_callback, prof);
+ return 1;
+}
+#else
+static int
+load_binaries (MonoProfiler *prof)
+{
+ return 0;
+}
+#endif
+
+static const char*
+symbol_for (uintptr_t code)
+{
+#ifdef HAVE_DLADDR
+ void *ip = (void*)code;
+ Dl_info di;
+ if (dladdr (ip, &di)) {
+ if (di.dli_sname)
+ return di.dli_sname;
+ } else {
+ /* char **names;
+ names = backtrace_symbols (&ip, 1);
+ if (names) {
+ const char* p = names [0];
+ g_free (names);
+ return p;
+ }
+ */
+ }
+#endif
+ return NULL;
+}
+
+static void
+dump_unmanaged_coderefs (MonoProfiler *prof)
+{
+ int i;
+ const char* last_symbol;
+ uintptr_t addr, page_end;
+
+ if (load_binaries (prof))
+ return;
+ for (i = 0; i < size_code_pages; ++i) {
+ const char* sym;
+ if (!code_pages [i] || code_pages [i] & 1)
+ continue;
+ last_symbol = NULL;
+ addr = CPAGE_ADDR (code_pages [i]);
+ page_end = addr + CPAGE_SIZE;
+ code_pages [i] |= 1;
+ /* we dump the symbols for the whole page */
+ for (; addr < page_end; addr += 16) {
+ sym = symbol_for (addr);
+ if (sym && sym == last_symbol)
+ continue;
+ last_symbol = sym;
+ if (!sym)
+ continue;
+ dump_usym (prof, sym, addr, 0); /* let's not guess the size */
+ //printf ("found symbol at %p: %s\n", (void*)addr, sym);
+ }
+ }
+}
+
+typedef struct MonoCounterAgent {
+ MonoCounter *counter;
+ // MonoCounterAgent specific data :
+ void *value;
+ size_t value_size;
+ short index;
+ short emitted;
+ struct MonoCounterAgent *next;
+} MonoCounterAgent;
+
+static MonoCounterAgent* counters;
+static int counters_index = 1;
+static mono_mutex_t counters_mutex;
+
+static void
+counters_add_agent (MonoCounter *counter)
+{
+ if (InterlockedRead (&in_shutdown))
+ return;
+
+ MonoCounterAgent *agent, *item;
+
+ mono_os_mutex_lock (&counters_mutex);
+
+ for (agent = counters; agent; agent = agent->next) {
+ if (agent->counter == counter) {
+ agent->value_size = 0;
+ if (agent->value) {
+ g_free (agent->value);
+ agent->value = NULL;
+ }
+ goto done;
+ }
+ }
+
+ agent = (MonoCounterAgent *) g_malloc (sizeof (MonoCounterAgent));
+ agent->counter = counter;
+ agent->value = NULL;
+ agent->value_size = 0;
+ agent->index = counters_index++;
+ agent->emitted = 0;
+ agent->next = NULL;
+
+ if (!counters) {
+ counters = agent;
+ } else {
+ item = counters;
+ while (item->next)
+ item = item->next;
+ item->next = agent;
+ }
+
+done:
+ mono_os_mutex_unlock (&counters_mutex);
+}
+
+static mono_bool
+counters_init_foreach_callback (MonoCounter *counter, gpointer data)
+{
+ counters_add_agent (counter);
+ return TRUE;
+}
+
+static void
+counters_init (MonoProfiler *profiler)
+{
+ mono_os_mutex_init (&counters_mutex);
+
+ mono_counters_on_register (&counters_add_agent);
+ mono_counters_foreach (counters_init_foreach_callback, NULL);
+}
+
+static void
+counters_emit (MonoProfiler *profiler)
+{
+ MonoCounterAgent *agent;
+ int len = 0;
+ int size =
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* len */
+ ;
+
+ mono_os_mutex_lock (&counters_mutex);
+
+ for (agent = counters; agent; agent = agent->next) {
+ if (agent->emitted)
+ continue;
+
+ size +=
+ LEB128_SIZE /* section */ +
+ strlen (mono_counter_get_name (agent->counter)) + 1 /* name */ +
+ BYTE_SIZE /* type */ +
+ BYTE_SIZE /* unit */ +
+ BYTE_SIZE /* variance */ +
+ LEB128_SIZE /* index */
+ ;
+
+ len++;
+ }
+
+ if (!len)
+ goto done;
+
+ ENTER_LOG (&counter_descriptors_ctr, logbuffer, size);
+
+ emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
+ emit_value (logbuffer, len);
+
+ for (agent = counters; agent; agent = agent->next) {
+ const char *name;
+
+ if (agent->emitted)
+ continue;
+
+ name = mono_counter_get_name (agent->counter);
+ emit_value (logbuffer, mono_counter_get_section (agent->counter));
+ emit_string (logbuffer, name, strlen (name) + 1);
+ emit_byte (logbuffer, mono_counter_get_type (agent->counter));
+ emit_byte (logbuffer, mono_counter_get_unit (agent->counter));
+ emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
+ emit_value (logbuffer, agent->index);
+
+ agent->emitted = 1;
+ }
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+done:
+ mono_os_mutex_unlock (&counters_mutex);
+}
+
+static void
+counters_sample (MonoProfiler *profiler, uint64_t timestamp)
+{
+ MonoCounterAgent *agent;
+ MonoCounter *counter;
+ int type;
+ int buffer_size;
+ void *buffer;
+ int size;
+
+ counters_emit (profiler);
+
+ buffer_size = 8;
+ buffer = g_calloc (1, buffer_size);
+
+ mono_os_mutex_lock (&counters_mutex);
+
+ size =
+ EVENT_SIZE /* event */
+ ;
+
+ for (agent = counters; agent; agent = agent->next) {
+ size +=
+ LEB128_SIZE /* index */ +
+ BYTE_SIZE /* type */ +
+ mono_counter_get_size (agent->counter) /* value */
+ ;
+ }
+
+ size +=
+ LEB128_SIZE /* stop marker */
+ ;
+
+ ENTER_LOG (&counter_samples_ctr, logbuffer, size);
+
+ emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
+
+ for (agent = counters; agent; agent = agent->next) {
+ size_t size;
+
+ counter = agent->counter;
+
+ size = mono_counter_get_size (counter);
+
+ if (size > buffer_size) {
+ buffer_size = size;
+ buffer = g_realloc (buffer, buffer_size);
+ }
+
+ memset (buffer, 0, buffer_size);
+
+ g_assert (mono_counters_sample (counter, buffer, size));
+
+ type = mono_counter_get_type (counter);
+
+ if (!agent->value) {
+ agent->value = g_calloc (1, size);
+ agent->value_size = size;
+ } else {
+ if (type == MONO_COUNTER_STRING) {
+ if (strcmp (agent->value, buffer) == 0)
+ continue;
+ } else {
+ if (agent->value_size == size && memcmp (agent->value, buffer, size) == 0)
+ continue;
+ }
+ }
+
+ emit_uvalue (logbuffer, agent->index);
+ emit_byte (logbuffer, type);
+ switch (type) {
+ case MONO_COUNTER_INT:
+#if SIZEOF_VOID_P == 4
+ case MONO_COUNTER_WORD:
+#endif
+ emit_svalue (logbuffer, *(int*)buffer - *(int*)agent->value);
+ break;
+ case MONO_COUNTER_UINT:
+ emit_uvalue (logbuffer, *(guint*)buffer - *(guint*)agent->value);
+ break;
+ case MONO_COUNTER_TIME_INTERVAL:
+ case MONO_COUNTER_LONG:
+#if SIZEOF_VOID_P == 8
+ case MONO_COUNTER_WORD:
+#endif
+ emit_svalue (logbuffer, *(gint64*)buffer - *(gint64*)agent->value);
+ break;
+ case MONO_COUNTER_ULONG:
+ emit_uvalue (logbuffer, *(guint64*)buffer - *(guint64*)agent->value);
+ break;
+ case MONO_COUNTER_DOUBLE:
+ emit_double (logbuffer, *(double*)buffer);
+ break;
+ case MONO_COUNTER_STRING:
+ if (size == 0) {
+ emit_byte (logbuffer, 0);
+ } else {
+ emit_byte (logbuffer, 1);
+ emit_string (logbuffer, (char*)buffer, size);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (type == MONO_COUNTER_STRING && size > agent->value_size) {
+ agent->value = g_realloc (agent->value, size);
+ agent->value_size = size;
+ }
+
+ if (size > 0)
+ memcpy (agent->value, buffer, size);
+ }
+ g_free (buffer);
+
+ emit_value (logbuffer, 0);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ mono_os_mutex_unlock (&counters_mutex);
+}
+
+typedef struct _PerfCounterAgent PerfCounterAgent;
+struct _PerfCounterAgent {
+ PerfCounterAgent *next;
+ int index;
+ char *category_name;
+ char *name;
+ int type;
+ gint64 value;
+ guint8 emitted;
+ guint8 updated;
+ guint8 deleted;
+};
+
+static PerfCounterAgent *perfcounters = NULL;
+
+static void
+perfcounters_emit (MonoProfiler *profiler)
+{
+ PerfCounterAgent *pcagent;
+ int len = 0;
+ int size =
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* len */
+ ;
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->emitted)
+ continue;
+
+ size +=
+ LEB128_SIZE /* section */ +
+ strlen (pcagent->category_name) + 1 /* category name */ +
+ strlen (pcagent->name) + 1 /* name */ +
+ BYTE_SIZE /* type */ +
+ BYTE_SIZE /* unit */ +
+ BYTE_SIZE /* variance */ +
+ LEB128_SIZE /* index */
+ ;
+
+ len++;
+ }
+
+ if (!len)
+ return;
+
+ ENTER_LOG (&perfcounter_descriptors_ctr, logbuffer, size);
+
+ emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
+ emit_value (logbuffer, len);
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->emitted)
+ continue;
+
+ emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
+ emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
+ emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
+ emit_byte (logbuffer, MONO_COUNTER_LONG);
+ emit_byte (logbuffer, MONO_COUNTER_RAW);
+ emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
+ emit_value (logbuffer, pcagent->index);
+
+ pcagent->emitted = 1;
+ }
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+static gboolean
+perfcounters_foreach (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data)
+{
+ PerfCounterAgent *pcagent;
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
+ continue;
+ if (pcagent->value == value)
+ return TRUE;
+
+ pcagent->value = value;
+ pcagent->updated = 1;
+ pcagent->deleted = 0;
+ return TRUE;
+ }
+
+ pcagent = g_new0 (PerfCounterAgent, 1);
+ pcagent->next = perfcounters;
+ pcagent->index = counters_index++;
+ pcagent->category_name = g_strdup (category_name);
+ pcagent->name = g_strdup (name);
+ pcagent->type = (int) type;
+ pcagent->value = value;
+ pcagent->emitted = 0;
+ pcagent->updated = 1;
+ pcagent->deleted = 0;
+
+ perfcounters = pcagent;
+
+ return TRUE;
+}
+
+static void
+perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
+{
+ PerfCounterAgent *pcagent;
+ int len = 0;
+ int size;
+
+ mono_os_mutex_lock (&counters_mutex);
+
+ /* mark all perfcounters as deleted, foreach will unmark them as necessary */
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next)
+ pcagent->deleted = 1;
+
+ mono_perfcounter_foreach (perfcounters_foreach, perfcounters);
+
+ perfcounters_emit (profiler);
+
+ size =
+ EVENT_SIZE /* event */
+ ;
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->deleted || !pcagent->updated)
+ continue;
+
+ size +=
+ LEB128_SIZE /* index */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* value */
+ ;
+
+ len++;
+ }
+
+ if (!len)
+ goto done;
+
+ size +=
+ LEB128_SIZE /* stop marker */
+ ;
+
+ ENTER_LOG (&perfcounter_samples_ctr, logbuffer, size);
+
+ emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->deleted || !pcagent->updated)
+ continue;
+ emit_uvalue (logbuffer, pcagent->index);
+ emit_byte (logbuffer, MONO_COUNTER_LONG);
+ emit_svalue (logbuffer, pcagent->value);
+
+ pcagent->updated = 0;
+ }
+
+ emit_value (logbuffer, 0);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+done:
+ mono_os_mutex_unlock (&counters_mutex);
+}
+
+static void
+counters_and_perfcounters_sample (MonoProfiler *prof)
+{
+ uint64_t now = current_time ();
+
+ counters_sample (prof, now);
+ perfcounters_sample (prof, now);
+}
+
+#define COVERAGE_DEBUG(x) if (debug_coverage) {x}
+static mono_mutex_t coverage_mutex;
+static MonoConcurrentHashTable *coverage_methods = NULL;
+static MonoConcurrentHashTable *coverage_assemblies = NULL;
+static MonoConcurrentHashTable *coverage_classes = NULL;
+
+static MonoConcurrentHashTable *filtered_classes = NULL;
+static MonoConcurrentHashTable *entered_methods = NULL;
+static MonoConcurrentHashTable *image_to_methods = NULL;
+static MonoConcurrentHashTable *suppressed_assemblies = NULL;
+static gboolean coverage_initialized = FALSE;
+
+static GPtrArray *coverage_data = NULL;
+static int previous_offset = 0;
+
+typedef struct {
+ MonoLockFreeQueueNode node;
+ MonoMethod *method;
+} MethodNode;
+
+typedef struct {
+ int offset;
+ int counter;
+ char *filename;
+ int line;
+ int column;
+} CoverageEntry;
+
+static void
+free_coverage_entry (gpointer data, gpointer userdata)
+{
+ CoverageEntry *entry = (CoverageEntry *)data;
+ g_free (entry->filename);
+ g_free (entry);
+}
+
+static void
+obtain_coverage_for_method (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)
+{
+ int offset = entry->iloffset - previous_offset;
+ CoverageEntry *e = g_new (CoverageEntry, 1);
+
+ previous_offset = entry->iloffset;
+
+ e->offset = offset;
+ e->counter = entry->counter;
+ e->filename = g_strdup(entry->filename ? entry->filename : "");
+ e->line = entry->line;
+ e->column = entry->col;
+
+ g_ptr_array_add (coverage_data, e);
+}
+
+static char *
+parse_generic_type_names(char *name)
+{
+ char *new_name, *ret;
+ int within_generic_declaration = 0, generic_members = 1;
+
+ if (name == NULL || *name == '\0')
+ return g_strdup ("");
+
+ if (!(ret = new_name = (char *) g_calloc (strlen (name) * 4 + 1, sizeof (char))))
+ return NULL;
+
+ do {
+ switch (*name) {
+ case '<':
+ within_generic_declaration = 1;
+ break;
+
+ case '>':
+ within_generic_declaration = 0;
+
+ if (*(name - 1) != '<') {
+ *new_name++ = '`';
+ *new_name++ = '0' + generic_members;
+ } else {
+ memcpy (new_name, "<>", 8);
+ new_name += 8;
+ }
+
+ generic_members = 0;
+ break;
+
+ case ',':
+ generic_members++;
+ break;
+
+ default:
+ if (!within_generic_declaration)
+ *new_name++ = *name;
+
+ break;
+ }
+ } while (*name++);
+
+ return ret;
+}
+
+static int method_id;
+static void
+build_method_buffer (gpointer key, gpointer value, gpointer userdata)
+{
+ MonoMethod *method = (MonoMethod *)value;
+ MonoProfiler *prof = (MonoProfiler *)userdata;
+ MonoClass *klass;
+ MonoImage *image;
+ char *class_name;
+ const char *image_name, *method_name, *sig, *first_filename;
+ guint i;
+
+ previous_offset = 0;
+ coverage_data = g_ptr_array_new ();
+
+ mono_profiler_coverage_get (prof, method, obtain_coverage_for_method);
+
+ klass = mono_method_get_class (method);
+ image = mono_class_get_image (klass);
+ image_name = mono_image_get_name (image);
+
+ sig = mono_signature_get_desc (mono_method_signature (method), TRUE);
+ class_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));
+ method_name = mono_method_get_name (method);
+
+ if (coverage_data->len != 0) {
+ CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[0];
+ first_filename = entry->filename ? entry->filename : "";
+ } else
+ first_filename = "";
+
+ image_name = image_name ? image_name : "";
+ sig = sig ? sig : "";
+ method_name = method_name ? method_name : "";
+
+ ENTER_LOG (&coverage_methods_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ strlen (image_name) + 1 /* image name */ +
+ strlen (class_name) + 1 /* class name */ +
+ strlen (method_name) + 1 /* method name */ +
+ strlen (sig) + 1 /* signature */ +
+ strlen (first_filename) + 1 /* first file name */ +
+ LEB128_SIZE /* token */ +
+ LEB128_SIZE /* method id */ +
+ LEB128_SIZE /* entries */
+ );
+
+ emit_event (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
+ emit_string (logbuffer, image_name, strlen (image_name) + 1);
+ emit_string (logbuffer, class_name, strlen (class_name) + 1);
+ emit_string (logbuffer, method_name, strlen (method_name) + 1);
+ emit_string (logbuffer, sig, strlen (sig) + 1);
+ emit_string (logbuffer, first_filename, strlen (first_filename) + 1);
+
+ emit_uvalue (logbuffer, mono_method_get_token (method));
+ emit_uvalue (logbuffer, method_id);
+ emit_value (logbuffer, coverage_data->len);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ for (i = 0; i < coverage_data->len; i++) {
+ CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[i];
+
+ ENTER_LOG (&coverage_statements_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method id */ +
+ LEB128_SIZE /* offset */ +
+ LEB128_SIZE /* counter */ +
+ LEB128_SIZE /* line */ +
+ LEB128_SIZE /* column */
+ );
+
+ emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
+ emit_uvalue (logbuffer, method_id);
+ emit_uvalue (logbuffer, entry->offset);
+ emit_uvalue (logbuffer, entry->counter);
+ emit_uvalue (logbuffer, entry->line);
+ emit_uvalue (logbuffer, entry->column);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+ }
+
+ method_id++;
+
+ g_free (class_name);
+
+ g_ptr_array_foreach (coverage_data, free_coverage_entry, NULL);
+ g_ptr_array_free (coverage_data, TRUE);
+ coverage_data = NULL;
+}
+
+/* This empties the queue */
+static guint
+count_queue (MonoLockFreeQueue *queue)
+{
+ MonoLockFreeQueueNode *node;
+ guint count = 0;
+
+ while ((node = mono_lock_free_queue_dequeue (queue))) {
+ count++;
+ mono_thread_hazardous_try_free (node, g_free);
+ }
+
+ return count;
+}
+
+static void
+build_class_buffer (gpointer key, gpointer value, gpointer userdata)
+{
+ MonoClass *klass = (MonoClass *)key;
+ MonoLockFreeQueue *class_methods = (MonoLockFreeQueue *)value;
+ MonoImage *image;
+ char *class_name;
+ const char *assembly_name;
+ int number_of_methods, partially_covered;
+ guint fully_covered;
+
+ image = mono_class_get_image (klass);
+ assembly_name = mono_image_get_name (image);
+ class_name = mono_type_get_name (mono_class_get_type (klass));
+
+ assembly_name = assembly_name ? assembly_name : "";
+ number_of_methods = mono_class_num_methods (klass);
+ fully_covered = count_queue (class_methods);
+ /* We don't handle partial covered yet */
+ partially_covered = 0;
+
+ ENTER_LOG (&coverage_classes_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ strlen (assembly_name) + 1 /* assembly name */ +
+ strlen (class_name) + 1 /* class name */ +
+ LEB128_SIZE /* no. methods */ +
+ LEB128_SIZE /* fully covered */ +
+ LEB128_SIZE /* partially covered */
+ );
+
+ emit_event (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
+ emit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);
+ emit_string (logbuffer, class_name, strlen (class_name) + 1);
+ emit_uvalue (logbuffer, number_of_methods);
+ emit_uvalue (logbuffer, fully_covered);
+ emit_uvalue (logbuffer, partially_covered);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ g_free (class_name);
+}
+
+static void
+get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)
+{
+ MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
+
+ *number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);
+ if (image_methods)
+ *fully_covered = count_queue (image_methods);
+ else
+ *fully_covered = 0;
+
+ // FIXME: We don't handle partially covered yet.
+ *partially_covered = 0;
+}
+
+static void
+build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)
+{
+ MonoAssembly *assembly = (MonoAssembly *)value;
+ MonoImage *image = mono_assembly_get_image (assembly);
+ const char *name, *guid, *filename;
+ int number_of_methods = 0, partially_covered = 0;
+ guint fully_covered = 0;
+
+ name = mono_image_get_name (image);
+ guid = mono_image_get_guid (image);
+ filename = mono_image_get_filename (image);
+
+ name = name ? name : "";
+ guid = guid ? guid : "";
+ filename = filename ? filename : "";
+
+ get_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);
+
+ ENTER_LOG (&coverage_assemblies_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ strlen (name) + 1 /* name */ +
+ strlen (guid) + 1 /* guid */ +
+ strlen (filename) + 1 /* file name */ +
+ LEB128_SIZE /* no. methods */ +
+ LEB128_SIZE /* fully covered */ +
+ LEB128_SIZE /* partially covered */
+ );
+
+ emit_event (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
+ emit_string (logbuffer, name, strlen (name) + 1);
+ emit_string (logbuffer, guid, strlen (guid) + 1);
+ emit_string (logbuffer, filename, strlen (filename) + 1);
+ emit_uvalue (logbuffer, number_of_methods);
+ emit_uvalue (logbuffer, fully_covered);
+ emit_uvalue (logbuffer, partially_covered);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+}
+
+static void
+dump_coverage (MonoProfiler *prof)
+{
+ if (!coverage_initialized)
+ return;
+
+ COVERAGE_DEBUG(fprintf (stderr, "Coverage: Started dump\n");)
+ method_id = 0;
+
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_foreach (coverage_assemblies, build_assembly_buffer, NULL);
+ mono_conc_hashtable_foreach (coverage_classes, build_class_buffer, NULL);
+ mono_conc_hashtable_foreach (coverage_methods, build_method_buffer, prof);
+ mono_os_mutex_unlock (&coverage_mutex);
+
+ COVERAGE_DEBUG(fprintf (stderr, "Coverage: Finished dump\n");)
+}
+
+static void
+process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method)
+{
+ MonoClass *klass;
+ MonoImage *image;
+
+ if (!coverage_initialized)
+ return;
+
+ klass = mono_method_get_class (method);
+ image = mono_class_get_image (klass);
+
+ if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)))
+ return;
+
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (entered_methods, method, method);
+ mono_os_mutex_unlock (&coverage_mutex);
+}
+
+static MonoLockFreeQueueNode *
+create_method_node (MonoMethod *method)
+{
+ MethodNode *node = (MethodNode *) g_malloc (sizeof (MethodNode));
+ mono_lock_free_queue_node_init ((MonoLockFreeQueueNode *) node, FALSE);
+ node->method = method;
+
+ return (MonoLockFreeQueueNode *) node;
+}
+
+static gboolean
+coverage_filter (MonoProfiler *prof, MonoMethod *method)
+{
+ MonoError error;
+ MonoClass *klass;
+ MonoImage *image;
+ MonoAssembly *assembly;
+ MonoMethodHeader *header;
+ guint32 iflags, flags, code_size;
+ char *fqn, *classname;
+ gboolean has_positive, found;
+ MonoLockFreeQueue *image_methods, *class_methods;
+ MonoLockFreeQueueNode *node;
+
+ g_assert (coverage_initialized && "Why are we being asked for coverage filter info when we're not doing coverage?");
+
+ COVERAGE_DEBUG(fprintf (stderr, "Coverage filter for %s\n", mono_method_get_name (method));)
+
+ flags = mono_method_get_flags (method, &iflags);
+ if ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) ||
+ (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/)) {
+ COVERAGE_DEBUG(fprintf (stderr, " Internal call or pinvoke - ignoring\n");)
+ return FALSE;
+ }
+
+ // Don't need to do anything else if we're already tracking this method
+ if (mono_conc_hashtable_lookup (coverage_methods, method)) {
+ COVERAGE_DEBUG(fprintf (stderr, " Already tracking\n");)
+ return TRUE;
+ }
+
+ klass = mono_method_get_class (method);
+ image = mono_class_get_image (klass);
+
+ // Don't handle coverage for the core assemblies
+ if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
+ return FALSE;
+
+ if (prof->coverage_filters) {
+ /* Check already filtered classes first */
+ if (mono_conc_hashtable_lookup (filtered_classes, klass)) {
+ COVERAGE_DEBUG(fprintf (stderr, " Already filtered\n");)
+ return FALSE;
+ }
+
+ classname = mono_type_get_name (mono_class_get_type (klass));
+
+ fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);
+
+ COVERAGE_DEBUG(fprintf (stderr, " Looking for %s in filter\n", fqn);)
+ // Check positive filters first
+ has_positive = FALSE;
+ found = FALSE;
+ for (guint i = 0; i < prof->coverage_filters->len; ++i) {
+ char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
+
+ if (filter [0] == '+') {
+ filter = &filter [1];
+
+ COVERAGE_DEBUG(fprintf (stderr, " Checking against +%s ...", filter);)
+
+ if (strstr (fqn, filter) != NULL) {
+ COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
+ found = TRUE;
+ } else
+ COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
+
+ has_positive = TRUE;
+ }
+ }
+
+ if (has_positive && !found) {
+ COVERAGE_DEBUG(fprintf (stderr, " Positive match was not found\n");)
+
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (filtered_classes, klass, klass);
+ mono_os_mutex_unlock (&coverage_mutex);
+ g_free (fqn);
+ g_free (classname);
+
+ return FALSE;
+ }
+
+ for (guint i = 0; i < prof->coverage_filters->len; ++i) {
+ // FIXME: Is substring search sufficient?
+ char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
+ if (filter [0] == '+')
+ continue;
+
+ // Skip '-'
+ filter = &filter [1];
+ COVERAGE_DEBUG(fprintf (stderr, " Checking against -%s ...", filter);)
+
+ if (strstr (fqn, filter) != NULL) {
+ COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
+
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (filtered_classes, klass, klass);
+ mono_os_mutex_unlock (&coverage_mutex);
+ g_free (fqn);
+ g_free (classname);
+
+ return FALSE;
+ } else
+ COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
+
+ }
+
+ g_free (fqn);
+ g_free (classname);
+ }
+
+ COVERAGE_DEBUG(fprintf (stderr, " Handling coverage for %s\n", mono_method_get_name (method));)
+ header = mono_method_get_header_checked (method, &error);
+ mono_error_cleanup (&error);
+
+ mono_method_header_get_code (header, &code_size, NULL);
+
+ assembly = mono_image_get_assembly (image);
+
+ // Need to keep the assemblies around for as long as they are kept in the hashtable
+ // Nunit, for example, has a habit of unloading them before the coverage statistics are
+ // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
+ mono_assembly_addref (assembly);
+
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (coverage_methods, method, method);
+ mono_conc_hashtable_insert (coverage_assemblies, assembly, assembly);
+ mono_os_mutex_unlock (&coverage_mutex);
+
+ image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
+
+ if (image_methods == NULL) {
+ image_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
+ mono_lock_free_queue_init (image_methods);
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (image_to_methods, image, image_methods);
+ mono_os_mutex_unlock (&coverage_mutex);
+ }
+
+ node = create_method_node (method);
+ mono_lock_free_queue_enqueue (image_methods, node);
+
+ class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (coverage_classes, klass);
+
+ if (class_methods == NULL) {
+ class_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
+ mono_lock_free_queue_init (class_methods);
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_insert (coverage_classes, klass, class_methods);
+ mono_os_mutex_unlock (&coverage_mutex);
+ }
+
+ node = create_method_node (method);
+ mono_lock_free_queue_enqueue (class_methods, node);
+
+ return TRUE;
+}
+
+#define LINE_BUFFER_SIZE 4096
+/* Max file limit of 128KB */
+#define MAX_FILE_SIZE 128 * 1024
+static char *
+get_file_content (FILE *stream)
+{
+ char *buffer;
+ ssize_t bytes_read;
+ long filesize;
+ int res, offset = 0;
+
+ res = fseek (stream, 0, SEEK_END);
+ if (res < 0)
+ return NULL;
+
+ filesize = ftell (stream);
+ if (filesize < 0)
+ return NULL;
+
+ res = fseek (stream, 0, SEEK_SET);
+ if (res < 0)
+ return NULL;
+
+ if (filesize > MAX_FILE_SIZE)
+ return NULL;
+
+ buffer = (char *) g_malloc ((filesize + 1) * sizeof (char));
+ while ((bytes_read = fread (buffer + offset, 1, LINE_BUFFER_SIZE, stream)) > 0)
+ offset += bytes_read;
+
+ /* NULL terminate our buffer */
+ buffer[filesize] = '\0';
+ return buffer;
+}
+
+static char *
+get_next_line (char *contents, char **next_start)
+{
+ char *p = contents;
+
+ if (p == NULL || *p == '\0') {
+ *next_start = NULL;
+ return NULL;
+ }
+
+ while (*p != '\n' && *p != '\0')
+ p++;
+
+ if (*p == '\n') {
+ *p = '\0';
+ *next_start = p + 1;
+ } else
+ *next_start = NULL;
+
+ return contents;
+}
+
+static void
+init_suppressed_assemblies (void)
+{
+ char *content;
+ char *line;
+ FILE *sa_file;
+
+ suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
+ sa_file = fopen (SUPPRESSION_DIR "/mono-profiler-log.suppression", "r");
+ if (sa_file == NULL)
+ return;
+
+ /* Don't need to free @content as it is referred to by the lines stored in @suppressed_assemblies */
+ content = get_file_content (sa_file);
+ if (content == NULL) {
+ g_error ("mono-profiler-log.suppression is greater than 128kb - aborting\n");
+ }
+
+ while ((line = get_next_line (content, &content))) {
+ line = g_strchomp (g_strchug (line));
+ /* No locking needed as we're doing initialization */
+ mono_conc_hashtable_insert (suppressed_assemblies, line, line);
+ }
+
+ fclose (sa_file);
+}
+
+static void
+parse_cov_filter_file (GPtrArray *filters, const char *file)
+{
+ FILE *filter_file;
+ char *line, *content;
+
+ filter_file = fopen (file, "r");
+ if (filter_file == NULL) {
+ fprintf (stderr, "Unable to open %s\n", file);
+ return;
+ }
+
+ /* Don't need to free content as it is referred to by the lines stored in @filters */
+ content = get_file_content (filter_file);
+ if (content == NULL)
+ fprintf (stderr, "WARNING: %s is greater than 128kb - ignoring\n", file);
+
+ while ((line = get_next_line (content, &content)))
+ g_ptr_array_add (filters, g_strchug (g_strchomp (line)));
+
+ fclose (filter_file);
+}
+
+static void
+coverage_init (MonoProfiler *prof)
+{
+ g_assert (!coverage_initialized && "Why are we initializing coverage twice?");
+
+ COVERAGE_DEBUG(fprintf (stderr, "Coverage initialized\n");)
+
+ mono_os_mutex_init (&coverage_mutex);
+ coverage_methods = mono_conc_hashtable_new (NULL, NULL);
+ coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
+ coverage_classes = mono_conc_hashtable_new (NULL, NULL);
+ filtered_classes = mono_conc_hashtable_new (NULL, NULL);
+ entered_methods = mono_conc_hashtable_new (NULL, NULL);
+ image_to_methods = mono_conc_hashtable_new (NULL, NULL);
+ init_suppressed_assemblies ();
+
+ coverage_initialized = TRUE;
+}
+
+static void
+unref_coverage_assemblies (gpointer key, gpointer value, gpointer userdata)
+{
+ MonoAssembly *assembly = (MonoAssembly *)value;
+ mono_assembly_close (assembly);
+}
+
+static void
+free_sample_hit (gpointer p)
+{
+ mono_lock_free_free (p, SAMPLE_BLOCK_SIZE);
+}
+
+static void
+cleanup_reusable_samples (MonoProfiler *prof)
+{
+ SampleHit *sample;
+
+ while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->sample_reuse_queue)))
+ mono_thread_hazardous_try_free (sample, free_sample_hit);
+}
+
+static void
+log_shutdown (MonoProfiler *prof)
+{
+ InterlockedWrite (&in_shutdown, 1);
+
+ if (!no_counters)
+ counters_and_perfcounters_sample (prof);
+
+ dump_coverage (prof);
+
+ char c = 1;
+
+ if (write (prof->pipes [1], &c, 1) != 1) {
+ fprintf (stderr, "Could not write to pipe: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ mono_native_thread_join (prof->helper_thread);
+
+ mono_os_mutex_destroy (&counters_mutex);
+
+ MonoCounterAgent *mc_next;
+
+ for (MonoCounterAgent *cur = counters; cur; cur = mc_next) {
+ mc_next = cur->next;
+ g_free (cur);
+ }
+
+ PerfCounterAgent *pc_next;
+
+ for (PerfCounterAgent *cur = perfcounters; cur; cur = pc_next) {
+ pc_next = cur->next;
+ g_free (cur);
+ }
+
+ /*
+ * Ensure that we empty the LLS completely, even if some nodes are
+ * not immediately removed upon calling mono_lls_remove (), by
+ * iterating until the head is NULL.
+ */
+ while (profiler_thread_list.head) {
+ MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+ g_assert (thread->attached && "Why is a thread in the LLS not attached?");
+
+ remove_thread (thread);
+ } MONO_LLS_FOREACH_SAFE_END
+ }
+
+ /*
+ * Ensure that all threads have been freed, so that we don't miss any
+ * buffers when we shut down the writer thread below.
+ */
+ mono_thread_hazardous_try_free_all ();
+
+ InterlockedWrite (&prof->run_dumper_thread, 0);
+ mono_os_sem_post (&prof->dumper_queue_sem);
+ mono_native_thread_join (prof->dumper_thread);
+ mono_os_sem_destroy (&prof->dumper_queue_sem);
+
+ InterlockedWrite (&prof->run_writer_thread, 0);
+ mono_os_sem_post (&prof->writer_queue_sem);
+ mono_native_thread_join (prof->writer_thread);
+ mono_os_sem_destroy (&prof->writer_queue_sem);
+
+ /*
+ * Free all writer queue entries, and ensure that all sample hits will be
+ * added to the sample reuse queue.
+ */
+ mono_thread_hazardous_try_free_all ();
+
+ cleanup_reusable_samples (prof);
+
+ /*
+ * Finally, make sure that all sample hits are freed. This should cover all
+ * hazardous data from the profiler. We can now be sure that the runtime
+ * won't later invoke free functions in the profiler library after it has
+ * been unloaded.
+ */
+ mono_thread_hazardous_try_free_all ();
+
+ g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why is the reader count still non-zero?");
+ g_assert (!InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why does someone still hold the exclusive lock?");
+
+#if defined (HAVE_SYS_ZLIB)
+ if (prof->gzfile)
+ gzclose (prof->gzfile);
+#endif
+ if (prof->pipe_output)
+ pclose (prof->file);
+ else
+ fclose (prof->file);
+
+ mono_conc_hashtable_destroy (prof->method_table);
+ mono_os_mutex_destroy (&prof->method_table_mutex);
+
+ if (coverage_initialized) {
+ mono_os_mutex_lock (&coverage_mutex);
+ mono_conc_hashtable_foreach (coverage_assemblies, unref_coverage_assemblies, prof);
+ mono_os_mutex_unlock (&coverage_mutex);
+
+ mono_conc_hashtable_destroy (coverage_methods);
+ mono_conc_hashtable_destroy (coverage_assemblies);
+ mono_conc_hashtable_destroy (coverage_classes);
+ mono_conc_hashtable_destroy (filtered_classes);
+
+ mono_conc_hashtable_destroy (entered_methods);
+ mono_conc_hashtable_destroy (image_to_methods);
+ mono_conc_hashtable_destroy (suppressed_assemblies);
+ mono_os_mutex_destroy (&coverage_mutex);
+ }
+
+ PROF_TLS_FREE ();
+
+ g_free (prof->args);
+ g_free (prof);
+}
+
+static char*
+new_filename (const char* filename)
+{
+ time_t t = time (NULL);
+ int pid = process_id ();
+ char pid_buf [16];
+ char time_buf [16];
+ char *res, *d;
+ const char *p;
+ int count_dates = 0;
+ int count_pids = 0;
+ int s_date, s_pid;
+ struct tm *ts;
+ for (p = filename; *p; p++) {
+ if (*p != '%')
+ continue;
+ p++;
+ if (*p == 't')
+ count_dates++;
+ else if (*p == 'p')
+ count_pids++;
+ else if (*p == 0)
+ break;
+ }
+ if (!count_dates && !count_pids)
+ return pstrdup (filename);
+ snprintf (pid_buf, sizeof (pid_buf), "%d", pid);
+ ts = gmtime (&t);
+ snprintf (time_buf, sizeof (time_buf), "%d%02d%02d%02d%02d%02d",
+ 1900 + ts->tm_year, 1 + ts->tm_mon, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
+ s_date = strlen (time_buf);
+ s_pid = strlen (pid_buf);
+ d = res = (char *) g_malloc (strlen (filename) + s_date * count_dates + s_pid * count_pids);
+ for (p = filename; *p; p++) {
+ if (*p != '%') {
+ *d++ = *p;
+ continue;
+ }
+ p++;
+ if (*p == 't') {
+ strcpy (d, time_buf);
+ d += s_date;
+ continue;
+ } else if (*p == 'p') {
+ strcpy (d, pid_buf);
+ d += s_pid;
+ continue;
+ } else if (*p == '%') {
+ *d++ = '%';
+ continue;
+ } else if (*p == 0)
+ break;
+ *d++ = '%';
+ *d++ = *p;
+ }
+ *d = 0;
+ return res;
+}
+
+static void
+add_to_fd_set (fd_set *set, int fd, int *max_fd)
+{
+ /*
+ * This should only trigger for the basic FDs (server socket, pipes) at
+ * startup if for some mysterious reason they're too large. In this case,
+ * the profiler really can't function, and we're better off printing an
+ * error and exiting.
+ */
+ if (fd >= FD_SETSIZE) {
+ fprintf (stderr, "File descriptor is out of bounds for fd_set: %d\n", fd);
+ exit (1);
+ }
+
+ FD_SET (fd, set);
+
+ if (*max_fd < fd)
+ *max_fd = fd;
+}
+
+static void *
+helper_thread (void *arg)
+{
+ MonoProfiler *prof = (MonoProfiler *) arg;
+
+ mono_threads_attach_tools_thread ();
+ mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
+
+ MonoProfilerThread *thread = init_thread (prof, FALSE);
+
+ GArray *command_sockets = g_array_new (FALSE, FALSE, sizeof (int));
+
+ while (1) {
+ fd_set rfds;
+ int max_fd = -1;
+
+ FD_ZERO (&rfds);
+
+ add_to_fd_set (&rfds, prof->server_socket, &max_fd);
+ add_to_fd_set (&rfds, prof->pipes [0], &max_fd);
+
+ for (gint i = 0; i < command_sockets->len; i++)
+ add_to_fd_set (&rfds, g_array_index (command_sockets, int, i), &max_fd);
+
+ struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
+
+ // Sleep for 1sec or until a file descriptor has data.
+ if (select (max_fd + 1, &rfds, NULL, NULL, &tv) == -1) {
+ if (errno == EINTR)
+ continue;
+
+ fprintf (stderr, "Error in mono-profiler-log server: %s", strerror (errno));
+ exit (1);
+ }
+
+ if (!no_counters)
+ counters_and_perfcounters_sample (prof);
+
+ buffer_lock_excl ();
+
+ sync_point (SYNC_POINT_PERIODIC);
+
+ buffer_unlock_excl ();
+
+ // Are we shutting down?
+ if (FD_ISSET (prof->pipes [0], &rfds)) {
+ char c;
+ read (prof->pipes [0], &c, 1);
+ break;
+ }
+
+ for (gint i = 0; i < command_sockets->len; i++) {
+ int fd = g_array_index (command_sockets, int, i);
+
+ if (!FD_ISSET (fd, &rfds))
+ continue;
+
+ char buf [64];
+ int len = read (fd, buf, sizeof (buf) - 1);
+
+ if (len == -1)
+ continue;
+
+ if (!len) {
+ // The other end disconnected.
+ g_array_remove_index (command_sockets, i);
+ close (fd);
+
+ continue;
+ }
+
+ buf [len] = 0;
+
+ if (!strcmp (buf, "heapshot\n") && hs_mode_ondemand) {
+ // Rely on the finalization callbacks invoking process_requests ().
+ heapshot_requested = 1;
+ mono_gc_finalize_notify ();
+ }
+ }
+
+ if (FD_ISSET (prof->server_socket, &rfds)) {
+ int fd = accept (prof->server_socket, NULL, NULL);
+
+ if (fd != -1) {
+ if (fd >= FD_SETSIZE)
+ close (fd);
+ else
+ g_array_append_val (command_sockets, fd);
+ }
+ }
+ }
+
+ for (gint i = 0; i < command_sockets->len; i++)
+ close (g_array_index (command_sockets, int, i));
+
+ g_array_free (command_sockets, TRUE);
+
+ send_log_unsafe (FALSE);
+ deinit_thread (thread);
+
+ mono_thread_info_detach ();
+
+ return NULL;
+}
+
+static void
+start_helper_thread (MonoProfiler* prof)
+{
+ if (pipe (prof->pipes) == -1) {
+ fprintf (stderr, "Cannot create pipe: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ prof->server_socket = socket (PF_INET, SOCK_STREAM, 0);
+
+ if (prof->server_socket == -1) {
+ fprintf (stderr, "Cannot create server socket: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ struct sockaddr_in server_address;
+
+ memset (&server_address, 0, sizeof (server_address));
+ server_address.sin_family = AF_INET;
+ server_address.sin_addr.s_addr = INADDR_ANY;
+ server_address.sin_port = htons (prof->command_port);
+
+ if (bind (prof->server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
+ fprintf (stderr, "Cannot bind server socket on port %d: %s\n", prof->command_port, strerror (errno));
+ close (prof->server_socket);
+ exit (1);
+ }
+
+ if (listen (prof->server_socket, 1) == -1) {
+ fprintf (stderr, "Cannot listen on server socket: %s\n", strerror (errno));
+ close (prof->server_socket);
+ exit (1);
+ }
+
+ socklen_t slen = sizeof (server_address);
+
+ if (getsockname (prof->server_socket, (struct sockaddr *) &server_address, &slen)) {
+ fprintf (stderr, "Could not get assigned port: %s\n", strerror (errno));
+ close (prof->server_socket);
+ exit (1);
+ }
+
+ prof->command_port = ntohs (server_address.sin_port);
+
+ if (!mono_native_thread_create (&prof->helper_thread, helper_thread, prof)) {
+ fprintf (stderr, "Could not start helper thread\n");
+ close (prof->server_socket);
+ exit (1);
+ }
+}
+
+static void
+free_writer_entry (gpointer p)
+{
+ mono_lock_free_free (p, WRITER_ENTRY_BLOCK_SIZE);
+}
+
+static gboolean
+handle_writer_queue_entry (MonoProfiler *prof)
+{
+ WriterQueueEntry *entry;
+
+ if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&prof->writer_queue))) {
+ if (!entry->methods)
+ goto no_methods;
+
+ gboolean wrote_methods = FALSE;
+
+ /*
+ * Encode the method events in a temporary log buffer that we
+ * flush to disk before the main buffer, ensuring that all
+ * methods have metadata emitted before they're referenced.
+ *
+ * We use a 'proper' thread-local buffer for this as opposed
+ * to allocating and freeing a buffer by hand because the call
+ * to mono_method_full_name () below may trigger class load
+ * events when it retrieves the signature of the method. So a
+ * thread-local buffer needs to exist when such events occur.
+ */
+ for (guint i = 0; i < entry->methods->len; i++) {
+ MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
+
+ if (mono_conc_hashtable_lookup (prof->method_table, info->method))
+ goto free_info; // This method already has metadata emitted.
+
+ /*
+ * Other threads use this hash table to get a general
+ * idea of whether a method has already been emitted to
+ * the stream. Due to the way we add to this table, it
+ * can easily happen that multiple threads queue up the
+ * same methods, but that's OK since eventually all
+ * methods will be in this table and the thread-local
+ * method lists will just be empty for the rest of the
+ * app's lifetime.
+ */
+ mono_os_mutex_lock (&prof->method_table_mutex);
+ mono_conc_hashtable_insert (prof->method_table, info->method, info->method);
+ mono_os_mutex_unlock (&prof->method_table_mutex);
+
+ char *name = mono_method_full_name (info->method, 1);
+ int nlen = strlen (name) + 1;
+ void *cstart = info->ji ? mono_jit_info_get_code_start (info->ji) : NULL;
+ int csize = info->ji ? mono_jit_info_get_code_size (info->ji) : 0;
+
+ ENTER_LOG (&method_jits_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */ +
+ LEB128_SIZE /* start */ +
+ LEB128_SIZE /* size */ +
+ nlen /* name */
+ );
+
+ emit_event_time (logbuffer, TYPE_JIT | TYPE_METHOD, info->time);
+ emit_method_inner (logbuffer, info->method);
+ emit_ptr (logbuffer, cstart);
+ emit_value (logbuffer, csize);
+
+ memcpy (logbuffer->cursor, name, nlen);
+ logbuffer->cursor += nlen;
+
+ EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
+
+ mono_free (name);
+
+ wrote_methods = TRUE;
+
+ free_info:
+ g_free (info);
+ }
+
+ g_ptr_array_free (entry->methods, TRUE);
+
+ if (wrote_methods) {
+ dump_buffer_threadless (prof, PROF_TLS_GET ()->buffer);
+ init_buffer_state (PROF_TLS_GET ());
+ }
+
+ no_methods:
+ dump_buffer (prof, entry->buffer);
+
+ mono_thread_hazardous_try_free (entry, free_writer_entry);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void *
+writer_thread (void *arg)
+{
+ MonoProfiler *prof = (MonoProfiler *)arg;
+
+ mono_threads_attach_tools_thread ();
+ mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler writer");
+
+ dump_header (prof);
+
+ MonoProfilerThread *thread = init_thread (prof, FALSE);
+
+ while (InterlockedRead (&prof->run_writer_thread)) {
+ mono_os_sem_wait (&prof->writer_queue_sem, MONO_SEM_FLAGS_NONE);
+ handle_writer_queue_entry (prof);
+ }
+
+ /* Drain any remaining entries on shutdown. */
+ while (handle_writer_queue_entry (prof));
+
+ free_buffer (thread->buffer, thread->buffer->size);
+ deinit_thread (thread);
+
+ mono_thread_info_detach ();
+
+ return NULL;
+}
+
+static void
+start_writer_thread (MonoProfiler* prof)
+{
+ InterlockedWrite (&prof->run_writer_thread, 1);
+
+ if (!mono_native_thread_create (&prof->writer_thread, writer_thread, prof)) {
+ fprintf (stderr, "Could not start writer thread\n");
+ exit (1);
+ }
+}
+
+static void
+reuse_sample_hit (gpointer p)
+{
+ SampleHit *sample = p;
+
+ mono_lock_free_queue_node_unpoison (&sample->node);
+ mono_lock_free_queue_enqueue (&sample->prof->sample_reuse_queue, &sample->node);
+}
+
+static gboolean
+handle_dumper_queue_entry (MonoProfiler *prof)
+{
+ SampleHit *sample;
+
+ if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->dumper_queue))) {
+ for (int i = 0; i < sample->count; ++i) {
+ MonoMethod *method = sample->frames [i].method;
+ MonoDomain *domain = sample->frames [i].domain;
+ void *address = sample->frames [i].base_address;
+
+ if (!method) {
+ g_assert (domain && "What happened to the domain pointer?");
+ g_assert (address && "What happened to the instruction pointer?");
+
+ MonoJitInfo *ji = mono_jit_info_table_find (domain, (char *) address);
+
+ if (ji)
+ sample->frames [i].method = mono_jit_info_get_method (ji);
+ }
+ }
+
+ ENTER_LOG (&sample_hits_ctr, logbuffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */ +
+ LEB128_SIZE /* count */ +
+ 1 * (
+ LEB128_SIZE /* ip */
+ ) +
+ LEB128_SIZE /* managed count */ +
+ sample->count * (
+ LEB128_SIZE /* method */
+ )
+ );
+
+ emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
+ emit_byte (logbuffer, SAMPLE_CYCLES);
+ emit_ptr (logbuffer, (void *) sample->tid);
+ emit_value (logbuffer, 1);
+
+ // TODO: Actual native unwinding.
+ for (int i = 0; i < 1; ++i) {
+ emit_ptr (logbuffer, sample->ip);
+ add_code_pointer ((uintptr_t) sample->ip);
+ }
+
+ /* new in data version 6 */
+ emit_uvalue (logbuffer, sample->count);
+
+ for (int i = 0; i < sample->count; ++i)
+ emit_method (logbuffer, sample->frames [i].method);
+
+ EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
+
+ mono_thread_hazardous_try_free (sample, reuse_sample_hit);
+
+ dump_unmanaged_coderefs (prof);
+ }
+
+ return FALSE;
+}
+
+static void *
+dumper_thread (void *arg)
+{
+ MonoProfiler *prof = (MonoProfiler *)arg;
+
+ mono_threads_attach_tools_thread ();
+ mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
+
+ MonoProfilerThread *thread = init_thread (prof, FALSE);
+
+ while (InterlockedRead (&prof->run_dumper_thread)) {
+ mono_os_sem_wait (&prof->dumper_queue_sem, MONO_SEM_FLAGS_NONE);
+ handle_dumper_queue_entry (prof);
+ }
+
+ /* Drain any remaining entries on shutdown. */
+ while (handle_dumper_queue_entry (prof));
+
+ send_log_unsafe (FALSE);
+ deinit_thread (thread);
+
+ mono_thread_info_detach ();
+
+ return NULL;
+}
+
+static void
+start_dumper_thread (MonoProfiler* prof)
+{
+ InterlockedWrite (&prof->run_dumper_thread, 1);
+
+ if (!mono_native_thread_create (&prof->dumper_thread, dumper_thread, prof)) {
+ fprintf (stderr, "Could not start dumper thread\n");
+ exit (1);
+ }
+}
+
+static void
+register_counter (const char *name, gint32 *counter)
+{
+ mono_counters_register (name, MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, counter);
+}
+
+static void
+runtime_initialized (MonoProfiler *profiler)
+{
+ InterlockedWrite (&runtime_inited, 1);
+
+ register_counter ("Sample events allocated", &sample_allocations_ctr);
+ register_counter ("Log buffers allocated", &buffer_allocations_ctr);
+
+ register_counter ("Event: Sync points", &sync_points_ctr);
+ register_counter ("Event: Heap objects", &heap_objects_ctr);
+ register_counter ("Event: Heap starts", &heap_starts_ctr);
+ register_counter ("Event: Heap ends", &heap_ends_ctr);
+ register_counter ("Event: Heap roots", &heap_roots_ctr);
+ register_counter ("Event: GC events", &gc_events_ctr);
+ register_counter ("Event: GC resizes", &gc_resizes_ctr);
+ register_counter ("Event: GC allocations", &gc_allocs_ctr);
+ register_counter ("Event: GC moves", &gc_moves_ctr);
+ register_counter ("Event: GC handle creations", &gc_handle_creations_ctr);
+ register_counter ("Event: GC handle deletions", &gc_handle_deletions_ctr);
+ register_counter ("Event: GC finalize starts", &finalize_begins_ctr);
+ register_counter ("Event: GC finalize ends", &finalize_ends_ctr);
+ register_counter ("Event: GC finalize object starts", &finalize_object_begins_ctr);
+ register_counter ("Event: GC finalize object ends", &finalize_object_ends_ctr);
+ register_counter ("Event: Image loads", &image_loads_ctr);
+ register_counter ("Event: Image unloads", &image_unloads_ctr);
+ register_counter ("Event: Assembly loads", &assembly_loads_ctr);
+ register_counter ("Event: Assembly unloads", &assembly_unloads_ctr);
+ register_counter ("Event: Class loads", &class_loads_ctr);
+ register_counter ("Event: Class unloads", &class_unloads_ctr);
+ register_counter ("Event: Method entries", &method_entries_ctr);
+ register_counter ("Event: Method exits", &method_exits_ctr);
+ register_counter ("Event: Method exception leaves", &method_exception_exits_ctr);
+ register_counter ("Event: Method JITs", &method_jits_ctr);
+ register_counter ("Event: Code buffers", &code_buffers_ctr);
+ register_counter ("Event: Exception throws", &exception_throws_ctr);
+ register_counter ("Event: Exception clauses", &exception_clauses_ctr);
+ register_counter ("Event: Monitor contentions", &monitor_contentions_ctr);
+ register_counter ("Event: Monitor acquisitions", &monitor_acquisitions_ctr);
+ register_counter ("Event: Monitor failures", &monitor_failures_ctr);
+ register_counter ("Event: Thread starts", &thread_starts_ctr);
+ register_counter ("Event: Thread ends", &thread_ends_ctr);
+ register_counter ("Event: Thread names", &thread_names_ctr);
+ register_counter ("Event: Domain loads", &domain_loads_ctr);
+ register_counter ("Event: Domain unloads", &domain_unloads_ctr);
+ register_counter ("Event: Domain names", &domain_names_ctr);
+ register_counter ("Event: Context loads", &context_loads_ctr);
+ register_counter ("Event: Context unloads", &context_unloads_ctr);
+ register_counter ("Event: Sample binaries", &sample_ubins_ctr);
+ register_counter ("Event: Sample symbols", &sample_usyms_ctr);
+ register_counter ("Event: Sample hits", &sample_hits_ctr);
+ register_counter ("Event: Counter descriptors", &counter_descriptors_ctr);
+ register_counter ("Event: Counter samples", &counter_samples_ctr);
+ register_counter ("Event: Performance counter descriptors", &perfcounter_descriptors_ctr);
+ register_counter ("Event: Performance counter samples", &perfcounter_samples_ctr);
+ register_counter ("Event: Coverage methods", &coverage_methods_ctr);
+ register_counter ("Event: Coverage statements", &coverage_statements_ctr);
+ register_counter ("Event: Coverage classes", &coverage_classes_ctr);
+ register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr);
+
+ counters_init (profiler);
+
+ /*
+ * We must start the helper thread before the writer thread. This is
+ * because the helper thread sets up the command port which is written to
+ * the log header by the writer thread.
+ */
+ start_helper_thread (profiler);
+ start_writer_thread (profiler);
+ start_dumper_thread (profiler);
+}
+
+static MonoProfiler*
+create_profiler (const char *args, const char *filename, GPtrArray *filters)
+{
+ MonoProfiler *prof;
+ char *nf;
+ int force_delete = 0;
+ prof = (MonoProfiler *) g_calloc (1, sizeof (MonoProfiler));
+
+ prof->args = pstrdup (args);
+ prof->command_port = command_port;
+ if (filename && *filename == '-') {
+ force_delete = 1;
+ filename++;
+ g_warning ("WARNING: the output:-FILENAME option is deprecated, the profiler now always overrides the output file\n");
+ }
+ if (!filename) {
+ if (do_report)
+ filename = "|mprof-report -";
+ else
+ filename = "output.mlpd";
+ nf = (char*)filename;
+ } else {
+ nf = new_filename (filename);
+ if (do_report) {
+ int s = strlen (nf) + 32;
+ char *p = (char *) g_malloc (s);
+ snprintf (p, s, "|mprof-report '--out=%s' -", nf);
+ g_free (nf);
+ nf = p;
+ }
+ }
+ if (*nf == '|') {
+ prof->file = popen (nf + 1, "w");
+ prof->pipe_output = 1;
+ } else if (*nf == '#') {
+ int fd = strtol (nf + 1, NULL, 10);
+ prof->file = fdopen (fd, "a");
+ } else {
+ if (force_delete)
+ unlink (nf);
+ prof->file = fopen (nf, "wb");
+ }
+ if (!prof->file) {
+ fprintf (stderr, "Cannot create profiler output: %s\n", nf);
+ exit (1);
+ }
+
+#if defined (HAVE_SYS_ZLIB)
+ if (use_zip)
+ prof->gzfile = gzdopen (fileno (prof->file), "wb");
+#endif
+
+ /*
+ * If you hit this assert while increasing MAX_FRAMES, you need to increase
+ * SAMPLE_BLOCK_SIZE as well.
+ */
+ g_assert (SAMPLE_SLOT_SIZE (MAX_FRAMES) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (SAMPLE_BLOCK_SIZE));
+
+ // FIXME: We should free this stuff too.
+ mono_lock_free_allocator_init_size_class (&prof->sample_size_class, SAMPLE_SLOT_SIZE (num_frames), SAMPLE_BLOCK_SIZE);
+ mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
+
+ mono_lock_free_queue_init (&prof->sample_reuse_queue);
+
+ g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
+
+ // FIXME: We should free this stuff too.
+ mono_lock_free_allocator_init_size_class (&prof->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
+ mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
+
+ mono_lock_free_queue_init (&prof->writer_queue);
+ mono_os_sem_init (&prof->writer_queue_sem, 0);
+
+ mono_lock_free_queue_init (&prof->dumper_queue);
+ mono_os_sem_init (&prof->dumper_queue_sem, 0);
+
+ mono_os_mutex_init (&prof->method_table_mutex);
+ prof->method_table = mono_conc_hashtable_new (NULL, NULL);
+
+ if (do_coverage)
+ coverage_init (prof);
+ prof->coverage_filters = filters;
+
+ prof->startup_time = current_time ();
+ return prof;
+}
+
+/*
+ * declaration to silence the compiler: this is the entry point that
+ * mono will load from the shared library and call.
+ */
+extern void
+mono_profiler_startup (const char *desc);
+
+extern void
+mono_profiler_startup_log (const char *desc);
+
+/*
+ * this is the entry point that will be used when the profiler
+ * is embedded inside the main executable.
+ */
+void
+mono_profiler_startup_log (const char *desc)
+{
+ mono_profiler_startup (desc);
+}
+
+static ProfilerConfig config;
+
+void
+mono_profiler_startup (const char *desc)
+{
+ GPtrArray *filters = NULL;
+ MonoProfiler *prof;
+
+ proflog_parse_args (&config, desc [3] == ':' ? desc + 4 : "");
+
+ //XXX maybe later cleanup to use config directly
+ nocalls = !(config.effective_mask & PROFLOG_CALL_EVENTS);
+ no_counters = !(config.effective_mask & PROFLOG_COUNTER_EVENTS);
+ do_report = config.do_report;
+ do_debug = config.do_debug;
+ do_heap_shot = (config.effective_mask & PROFLOG_HEAPSHOT_FEATURE);
+ hs_mode_ondemand = config.hs_mode_ondemand;
+ hs_mode_ms = config.hs_mode_ms;
+ hs_mode_gc = config.hs_mode_gc;
+ do_mono_sample = (config.effective_mask & PROFLOG_SAMPLING_FEATURE);
+ use_zip = config.use_zip;
+ command_port = config.command_port;
+ num_frames = config.num_frames;
+ notraces = config.notraces;
+ max_allocated_sample_hits = config.max_allocated_sample_hits;
+ max_call_depth = config.max_call_depth;
+ do_coverage = (config.effective_mask & PROFLOG_CODE_COV_FEATURE);
+ debug_coverage = config.debug_coverage;
+ only_coverage = config.only_coverage;
+
+ if (config.cov_filter_files) {
+ filters = g_ptr_array_new ();
+ int i;
+ for (i = 0; i < config.cov_filter_files->len; ++i) {
+ const char *name = config.cov_filter_files->pdata [i];
+ parse_cov_filter_file (filters, name);
+ }
+ }
+
+ init_time ();
+
+ PROF_TLS_INIT ();
+
+ prof = create_profiler (desc, config.output_filename, filters);
+ if (!prof) {
+ PROF_TLS_FREE ();
+ return;
+ }
+
+ mono_lls_init (&profiler_thread_list, NULL);
+
+ init_thread (prof, TRUE);
+
+ //This two events are required for the profiler to work
+ int events = MONO_PROFILE_THREADS | MONO_PROFILE_GC;
+
+ //Required callbacks
+ mono_profiler_install (prof, log_shutdown);
+ mono_profiler_install_runtime_initialized (runtime_initialized);
+
+ mono_profiler_install_gc (gc_event, gc_resize);
+ mono_profiler_install_thread (thread_start, thread_end);
+
+ //It's questionable whether we actually want this to be mandatory, maybe put it behind the actual event?
+ mono_profiler_install_thread_name (thread_name);
+
+
+ if (config.effective_mask & PROFLOG_DOMAIN_EVENTS) {
+ events |= MONO_PROFILE_APPDOMAIN_EVENTS;
+ mono_profiler_install_appdomain (NULL, domain_loaded, domain_unloaded, NULL);
+ mono_profiler_install_appdomain_name (domain_name);
+ }
+
+ if (config.effective_mask & PROFLOG_ASSEMBLY_EVENTS) {
+ events |= MONO_PROFILE_ASSEMBLY_EVENTS;
+ mono_profiler_install_assembly (NULL, assembly_loaded, assembly_unloaded, NULL);
+ }
+
+ if (config.effective_mask & PROFLOG_MODULE_EVENTS) {
+ events |= MONO_PROFILE_MODULE_EVENTS;
+ mono_profiler_install_module (NULL, image_loaded, image_unloaded, NULL);
+ }
+
+ if (config.effective_mask & PROFLOG_CLASS_EVENTS) {
+ events |= MONO_PROFILE_CLASS_EVENTS;
+ mono_profiler_install_class (NULL, class_loaded, class_unloaded, NULL);
+ }
+
+ if (config.effective_mask & PROFLOG_JIT_COMPILATION_EVENTS) {
+ events |= MONO_PROFILE_JIT_COMPILATION;
+ mono_profiler_install_jit_end (method_jitted);
+ mono_profiler_install_code_buffer_new (code_buffer_new);
+ }
+
+ if (config.effective_mask & PROFLOG_EXCEPTION_EVENTS) {
+ events |= MONO_PROFILE_EXCEPTIONS;
+ mono_profiler_install_exception (throw_exc, method_exc_leave, clause_exc);
+ }
+
+ if (config.effective_mask & PROFLOG_ALLOCATION_EVENTS) {
+ events |= MONO_PROFILE_ALLOCATIONS;
+ mono_profiler_install_allocation (gc_alloc);
+ }
+
+ //PROFLOG_GC_EVENTS is mandatory
+ //PROFLOG_THREAD_EVENTS is mandatory
+
+ if (config.effective_mask & PROFLOG_CALL_EVENTS) {
+ events |= MONO_PROFILE_ENTER_LEAVE;
+ mono_profiler_install_enter_leave (method_enter, method_leave);
+ }
+
+ if (config.effective_mask & PROFLOG_INS_COVERAGE_EVENTS) {
+ events |= MONO_PROFILE_INS_COVERAGE;
+ mono_profiler_install_coverage_filter (coverage_filter);
+ }
+
+ //XXX should we check for PROFLOG_SAMPLING_FEATURE instead??
+ if (config.effective_mask & PROFLOG_SAMPLING_EVENTS) {
+ events |= MONO_PROFILE_STATISTICAL;
+ mono_profiler_set_statistical_mode (config.sampling_mode, config.sample_freq);
+ mono_profiler_install_statistical (mono_sample_hit);
+ }
+
+ if (config.effective_mask & PROFLOG_MONITOR_EVENTS) {
+ events |= MONO_PROFILE_MONITOR_EVENTS;
+ mono_profiler_install_monitor (monitor_event);
+ }
+
+ if (config.effective_mask & PROFLOG_GC_MOVES_EVENTS) {
+ events |= MONO_PROFILE_GC_MOVES;
+ mono_profiler_install_gc_moves (gc_moves);
+ }
+
+ // TODO split those in two profiler events
+ if (config.effective_mask & (PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS)) {
+ events |= MONO_PROFILE_GC_ROOTS;
+ mono_profiler_install_gc_roots (
+ config.effective_mask & (PROFLOG_GC_HANDLE_EVENTS) ? gc_handle : NULL,
+ (config.effective_mask & PROFLOG_GC_ROOT_EVENTS) ? gc_roots : NULL);
+ }
+
+ if (config.effective_mask & PROFLOG_CONTEXT_EVENTS) {
+ events |= MONO_PROFILE_CONTEXT_EVENTS;
+ mono_profiler_install_context (context_loaded, context_unloaded);
+ }
+
+ if (config.effective_mask & PROFLOG_FINALIZATION_EVENTS) {
+ events |= MONO_PROFILE_GC_FINALIZATION;
+ mono_profiler_install_gc_finalize (finalize_begin, finalize_object_begin, finalize_object_end, finalize_end);
+ }
+
+ //PROFLOG_COUNTER_EVENTS is a pseudo event controled by the no_counters global var
+ //PROFLOG_GC_HANDLE_EVENTS is handled together with PROFLOG_GC_ROOT_EVENTS
+
+ mono_profiler_set_events ((MonoProfileFlags)events);
+}
--- /dev/null
+#ifndef __MONO_PROFLOG_H__
+#define __MONO_PROFLOG_H__
+
+#include <glib.h>
+#include <mono/metadata/profiler.h>
+
+#define BUF_ID 0x4D504C01
+#define LOG_HEADER_ID 0x4D505A01
+#define LOG_VERSION_MAJOR 1
+#define LOG_VERSION_MINOR 1
+#define LOG_DATA_VERSION 13
+
+/*
+ * Changes in major/minor versions:
+ * version 1.0: removed sysid field from header
+ * added args, arch, os fields to header
+ *
+ * Changes in data versions:
+ * version 2: added offsets in heap walk
+ * version 3: added GC roots
+ * version 4: added sample/statistical profiling
+ * version 5: added counters sampling
+ * version 6: added optional backtrace in sampling info
+ * version 8: added TYPE_RUNTIME and JIT helpers/trampolines
+ * version 9: added MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING
+ * version 10: added TYPE_COVERAGE
+ * version 11: added thread ID to TYPE_SAMPLE_HIT
+ added more load/unload events
+ unload for class
+ unload for image
+ load/unload for appdomain
+ load/unload for contexts
+ load/unload/name for assemblies
+ removed TYPE_LOAD_ERR flag (profiler never generated it, now removed from the format itself)
+ added TYPE_GC_HANDLE_{CREATED,DESTROYED}_BT
+ TYPE_JIT events are no longer guaranteed to have code start/size info (can be zero)
+ * version 12: added MONO_COUNTER_PROFILER
+ * version 13: added MONO_GC_EVENT_{PRE_STOP_WORLD_LOCKED,POST_START_WORLD_UNLOCKED}
+ added TYPE_META + TYPE_SYNC_POINT
+ removed il and native offset in TYPE_SAMPLE_HIT
+ methods in backtraces are now encoded as proper method pointers
+ removed flags in backtrace format
+ removed flags in metadata events
+ changed the following fields to a single byte rather than leb128
+ TYPE_GC_EVENT: event_type, generation
+ TYPE_HEAP_ROOT: root_type
+ TYPE_JITHELPER: type
+ TYPE_SAMPLE_HIT: sample_type
+ TYPE_CLAUSE: clause_type
+ TYPE_SAMPLE_COUNTERS_DESC: type, unit, variance
+ TYPE_SAMPLE_COUNTERS: type
+ added time fields to all events that were missing one
+ TYPE_HEAP_OBJECT
+ TYPE_HEAP_ROOT
+ TYPE_SAMPLE_USYM
+ TYPE_SAMPLE_COUNTERS_DESC
+ TYPE_COVERAGE_METHOD
+ TYPE_COVERAGE_STATEMENT
+ TYPE_COVERAGE_CLASS
+ TYPE_COVERAGE_ASSEMBLY
+ moved the time field in TYPE_SAMPLE_HIT to right after the event byte, now encoded as a regular time field
+ changed the time field in TYPE_SAMPLE_COUNTERS to be encoded as a regular time field (in nanoseconds)
+ added TYPE_GC_FINALIZE_{START,END,OBJECT_START,OBJECT_END}
+ */
+
+enum {
+ TYPE_ALLOC,
+ TYPE_GC,
+ TYPE_METADATA,
+ TYPE_METHOD,
+ TYPE_EXCEPTION,
+ TYPE_MONITOR,
+ TYPE_HEAP,
+ TYPE_SAMPLE,
+ TYPE_RUNTIME,
+ TYPE_COVERAGE,
+ TYPE_META,
+ /* extended type for TYPE_HEAP */
+ TYPE_HEAP_START = 0 << 4,
+ TYPE_HEAP_END = 1 << 4,
+ TYPE_HEAP_OBJECT = 2 << 4,
+ TYPE_HEAP_ROOT = 3 << 4,
+ /* extended type for TYPE_METADATA */
+ TYPE_END_LOAD = 2 << 4,
+ TYPE_END_UNLOAD = 4 << 4,
+ /* extended type for TYPE_GC */
+ TYPE_GC_EVENT = 1 << 4,
+ TYPE_GC_RESIZE = 2 << 4,
+ TYPE_GC_MOVE = 3 << 4,
+ TYPE_GC_HANDLE_CREATED = 4 << 4,
+ TYPE_GC_HANDLE_DESTROYED = 5 << 4,
+ TYPE_GC_HANDLE_CREATED_BT = 6 << 4,
+ TYPE_GC_HANDLE_DESTROYED_BT = 7 << 4,
+ TYPE_GC_FINALIZE_START = 8 << 4,
+ TYPE_GC_FINALIZE_END = 9 << 4,
+ TYPE_GC_FINALIZE_OBJECT_START = 10 << 4,
+ TYPE_GC_FINALIZE_OBJECT_END = 11 << 4,
+ /* extended type for TYPE_METHOD */
+ TYPE_LEAVE = 1 << 4,
+ TYPE_ENTER = 2 << 4,
+ TYPE_EXC_LEAVE = 3 << 4,
+ TYPE_JIT = 4 << 4,
+ /* extended type for TYPE_EXCEPTION */
+ TYPE_THROW_NO_BT = 0 << 7,
+ TYPE_THROW_BT = 1 << 7,
+ TYPE_CLAUSE = 1 << 4,
+ /* extended type for TYPE_ALLOC */
+ TYPE_ALLOC_NO_BT = 0 << 4,
+ TYPE_ALLOC_BT = 1 << 4,
+ /* extended type for TYPE_MONITOR */
+ TYPE_MONITOR_NO_BT = 0 << 7,
+ TYPE_MONITOR_BT = 1 << 7,
+ /* extended type for TYPE_SAMPLE */
+ TYPE_SAMPLE_HIT = 0 << 4,
+ TYPE_SAMPLE_USYM = 1 << 4,
+ TYPE_SAMPLE_UBIN = 2 << 4,
+ TYPE_SAMPLE_COUNTERS_DESC = 3 << 4,
+ TYPE_SAMPLE_COUNTERS = 4 << 4,
+ /* extended type for TYPE_RUNTIME */
+ TYPE_JITHELPER = 1 << 4,
+ /* extended type for TYPE_COVERAGE */
+ TYPE_COVERAGE_ASSEMBLY = 0 << 4,
+ TYPE_COVERAGE_METHOD = 1 << 4,
+ TYPE_COVERAGE_STATEMENT = 2 << 4,
+ TYPE_COVERAGE_CLASS = 3 << 4,
+ /* extended type for TYPE_META */
+ TYPE_SYNC_POINT = 0 << 4,
+ TYPE_END
+};
+
+enum {
+ /* metadata type byte for TYPE_METADATA */
+ TYPE_CLASS = 1,
+ TYPE_IMAGE = 2,
+ TYPE_ASSEMBLY = 3,
+ TYPE_DOMAIN = 4,
+ TYPE_THREAD = 5,
+ TYPE_CONTEXT = 6,
+};
+
+typedef enum {
+ SYNC_POINT_PERIODIC,
+ SYNC_POINT_WORLD_STOP,
+ SYNC_POINT_WORLD_START
+} MonoProfilerSyncPointType;
+
+// Sampling sources
+// Unless you have compiled with --enable-perf-events, only SAMPLE_CYCLES is available
+enum {
+ SAMPLE_CYCLES = 1,
+ SAMPLE_INSTRUCTIONS,
+ SAMPLE_CACHE_MISSES,
+ SAMPLE_CACHE_REFS,
+ SAMPLE_BRANCHES,
+ SAMPLE_BRANCH_MISSES,
+ SAMPLE_LAST
+};
+
+
+// If you alter MAX_FRAMES, you may need to alter SAMPLE_BLOCK_SIZE too.
+#define MAX_FRAMES 32
+
+//The following flags control emitting individual events
+#define PROFLOG_DOMAIN_EVENTS (1 << 0)
+#define PROFLOG_ASSEMBLY_EVENTS (1 << 1)
+#define PROFLOG_MODULE_EVENTS (1 << 2)
+#define PROFLOG_CLASS_EVENTS (1 << 3)
+#define PROFLOG_JIT_COMPILATION_EVENTS (1 << 4)
+#define PROFLOG_EXCEPTION_EVENTS (1 << 5)
+#define PROFLOG_ALLOCATION_EVENTS (1 << 6)
+#define PROFLOG_GC_EVENTS (1 << 7)
+#define PROFLOG_THREAD_EVENTS (1 << 8)
+//This generate enter/leave events
+#define PROFLOG_CALL_EVENTS (1 << 9)
+#define PROFLOG_INS_COVERAGE_EVENTS (1 << 10)
+#define PROFLOG_SAMPLING_EVENTS (1 << 11)
+#define PROFLOG_MONITOR_EVENTS (1 << 12)
+#define PROFLOG_GC_MOVES_EVENTS (1 << 13)
+
+#define PROFLOG_GC_ROOT_EVENTS (1 << 14)
+#define PROFLOG_CONTEXT_EVENTS (1 << 15)
+#define PROFLOG_FINALIZATION_EVENTS (1 << 16)
+#define PROFLOG_COUNTER_EVENTS (1 << 17)
+#define PROFLOG_GC_HANDLE_EVENTS (1 << 18)
+
+//The following flags control whole subsystems
+//Enables code coverage generation
+#define PROFLOG_CODE_COV_FEATURE (1 << 19)
+//This enables sampling to be generated
+#define PROFLOG_SAMPLING_FEATURE (1 << 20)
+//This enable heap dumping during GCs and filter GCRoots and GCHandle events outside of the dumped collections
+#define PROFLOG_HEAPSHOT_FEATURE (1 << 21)
+
+
+
+//The follow flags are the common aliases we want ppl to use
+#define PROFLOG_TYPELOADING_ALIAS (PROFLOG_DOMAIN_EVENTS | PROFLOG_ASSEMBLY_EVENTS | PROFLOG_MODULE_EVENTS | PROFLOG_CLASS_EVENTS)
+#define PROFLOG_CODECOV_ALIAS (PROFLOG_GC_EVENTS | PROFLOG_THREAD_EVENTS | PROFLOG_CALL_EVENTS | PROFLOG_INS_COVERAGE_EVENTS | PROFLOG_CODE_COV_FEATURE)
+#define PROFLOG_PERF_SAMPLING_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_SAMPLING_EVENTS | PROFLOG_SAMPLING_FEATURE)
+#define PROFLOG_GC_ALLOC_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_ALLOCATION_EVENTS)
+#define PROFLOG_HEAPSHOT_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_HEAPSHOT_FEATURE)
+#define PROFLOG_LEGACY_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_GC_EVENTS | PROFLOG_THREAD_EVENTS | PROFLOG_JIT_COMPILATION_EVENTS | PROFLOG_EXCEPTION_EVENTS | PROFLOG_MONITOR_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_CONTEXT_EVENTS | PROFLOG_FINALIZATION_EVENTS | PROFLOG_COUNTER_EVENTS)
+
+
+typedef struct {
+ //Events explicitly enabled
+ int enable_mask;
+ //Events explicitly disabled
+ int disable_mask;
+
+ //Actual mask the profiler should use
+ int effective_mask;
+
+ //Emit a report at the end of execution
+ gboolean do_report;
+
+ //Enable profiler internal debugging
+ gboolean do_debug;
+
+ //Enable code coverage specific debugging
+ gboolean debug_coverage;
+
+ //Where to compress the output file
+ gboolean use_zip;
+
+ //If true, don't generate stacktraces
+ gboolean notraces;
+
+ //If true, emit coverage but don't emit enter/exit events - this happens cuz they share an event
+ gboolean only_coverage;
+
+ //If true, heapshots are generated on demand only
+ gboolean hs_mode_ondemand;
+
+ //HeapShort frequency in milliseconds
+ unsigned int hs_mode_ms;
+
+ //HeapShort frequency in number of collections
+ unsigned int hs_mode_gc;
+
+ //Sample frequency in Hertz
+ int sample_freq;
+
+ //Maximum number of frames to collect
+ int num_frames;
+
+ //Max depth to record enter/leave events
+ int max_call_depth;
+
+ //Name of the generated mlpd file
+ const char *output_filename;
+
+ //Filter files used by the code coverage mode
+ GPtrArray *cov_filter_files;
+
+ //Port to listen for profiling commands
+ int command_port;
+
+ //Max size of the sample hit buffer, we'll drop frames if it's reached
+ int max_allocated_sample_hits;
+
+ MonoProfileSamplingMode sampling_mode;
+} ProfilerConfig;
+
+void proflog_parse_args (ProfilerConfig *config, const char *desc);
+
+#endif /* __MONO_PROFLOG_H__ */
+++ /dev/null
-/*
- * mono-profiler-aot.c: Ahead of Time Compiler Profiler for Mono.
- *
- *
- * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
- *
- * This profiler collects profiling information usable by the Mono AOT compiler
- * to generate better code. It saves the information into files under ~/.mono.
- * The AOT compiler can load these files during compilation.
- * Currently, only the order in which methods were compiled is saved,
- * allowing more efficient function ordering in the AOT files.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#include "mono-profiler-aot.h"
-
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/class-internals.h>
-#include <mono/utils/mono-os-mutex.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <sys/stat.h>
-
-#ifdef HOST_WIN32
-#include <direct.h>
-#endif
-
-struct _MonoProfiler {
- GHashTable *classes;
- GHashTable *images;
- GPtrArray *methods;
- FILE *outfile;
- int id;
- char *outfile_name;
-};
-
-static mono_mutex_t mutex;
-static gboolean verbose;
-
-static void
-prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
-{
-}
-
-static void
-prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
-{
- MonoImage *image = mono_class_get_image (mono_method_get_class (method));
-
- if (!image->assembly || method->wrapper_type)
- return;
-
- mono_os_mutex_lock (&mutex);
- g_ptr_array_add (prof->methods, method);
- mono_os_mutex_unlock (&mutex);
-}
-
-static void
-prof_shutdown (MonoProfiler *prof);
-
-static void
-usage (int do_exit)
-{
- printf ("AOT profiler.\n");
- printf ("Usage: mono --profile=aot[:OPTION1[,OPTION2...]] program.exe\n");
- printf ("Options:\n");
- printf ("\thelp show this usage info\n");
- printf ("\toutput=FILENAME write the data to file FILENAME (required)\n");
- printf ("\tverbose print diagnostic info\n");
- if (do_exit)
- exit (1);
-}
-
-static const char*
-match_option (const char* p, const char *opt, char **rval)
-{
- int len = strlen (opt);
- if (strncmp (p, opt, len) == 0) {
- if (rval) {
- if (p [len] == '=' && p [len + 1]) {
- const char *opt = p + len + 1;
- const char *end = strchr (opt, ',');
- char *val;
- int l;
- if (end == NULL) {
- l = strlen (opt);
- } else {
- l = end - opt;
- }
- val = (char *) g_malloc (l + 1);
- memcpy (val, opt, l);
- val [l] = 0;
- *rval = val;
- return opt + l;
- }
- if (p [len] == 0 || p [len] == ',') {
- *rval = NULL;
- return p + len + (p [len] == ',');
- }
- usage (1);
- } else {
- if (p [len] == 0)
- return p + len;
- if (p [len] == ',')
- return p + len + 1;
- }
- }
- return p;
-}
-
-void
-mono_profiler_startup (const char *desc);
-
-/**
- * mono_profiler_startup:
- * the entry point
- */
-void
-mono_profiler_startup (const char *desc)
-{
- MonoProfiler *prof;
- const char *p;
- const char *opt;
- char *outfile_name;
-
- p = desc;
- if (strncmp (p, "aot", 3))
- usage (1);
- p += 3;
- if (*p == ':')
- p++;
- for (; *p; p = opt) {
- char *val;
- if (*p == ',') {
- opt = p + 1;
- continue;
- }
- if ((opt = match_option (p, "help", NULL)) != p) {
- usage (0);
- continue;
- }
- if ((opt = match_option (p, "verbose", NULL)) != p) {
- verbose = TRUE;
- continue;
- }
- if ((opt = match_option (p, "output", &val)) != p) {
- outfile_name = val;
- continue;
- }
- fprintf (stderr, "mono-profiler-aot: Unknown option: '%s'.\n", p);
- exit (1);
- }
-
- if (!outfile_name) {
- fprintf (stderr, "mono-profiler-aot: The 'output' argument is required.\n");
- exit (1);
- }
-
- prof = g_new0 (MonoProfiler, 1);
- prof->images = g_hash_table_new (NULL, NULL);
- prof->classes = g_hash_table_new (NULL, NULL);
- prof->methods = g_ptr_array_new ();
- prof->outfile_name = outfile_name;
-
- mono_os_mutex_init (&mutex);
-
- mono_profiler_install (prof, prof_shutdown);
-
- mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
-
- mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
-}
-
-static void
-emit_byte (MonoProfiler *prof, guint8 value)
-{
- fwrite (&value, 1, 1, prof->outfile);
-}
-
-static void
-emit_int32 (MonoProfiler *prof, int value)
-{
- // FIXME: Endianness
- fwrite (&value, 4, 1, prof->outfile);
-}
-
-static void
-emit_string (MonoProfiler *prof, const char *str)
-{
- int len = strlen (str);
-
- emit_int32 (prof, len);
- fwrite (str, len, 1, prof->outfile);
-}
-
-static void
-emit_record (MonoProfiler *prof, AotProfRecordType type, int id)
-{
- emit_byte (prof, type);
- emit_int32 (prof, id);
-}
-
-static int
-add_image (MonoProfiler *prof, MonoImage *image)
-{
- int id = GPOINTER_TO_INT (g_hash_table_lookup (prof->images, image));
- if (id)
- return id - 1;
-
- id = prof->id ++;
- emit_record (prof, AOTPROF_RECORD_IMAGE, id);
- emit_string (prof, image->assembly->aname.name);
- emit_string (prof, image->guid);
- g_hash_table_insert (prof->images, image, GINT_TO_POINTER (id + 1));
- return id;
-}
-
-static int
-add_class (MonoProfiler *prof, MonoClass *klass);
-
-static int
-add_type (MonoProfiler *prof, MonoType *type)
-{
- switch (type->type) {
-#if 0
- case MONO_TYPE_SZARRAY: {
- int eid = add_type (prof, &type->data.klass->byval_arg);
- if (eid == -1)
- return -1;
- int id = prof->id ++;
- emit_record (prof, AOTPROF_RECORD_TYPE, id);
- emit_byte (prof, MONO_TYPE_SZARRAY);
- emit_int32 (prof, id);
- return id;
- }
-#endif
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_GENERICINST:
- return add_class (prof, mono_class_from_mono_type (type));
- default:
- return -1;
- }
-}
-
-static int
-add_ginst (MonoProfiler *prof, MonoGenericInst *inst)
-{
- int i, id;
- int *ids;
-
- // FIXME: Cache
- ids = g_malloc0 (inst->type_argc * sizeof (int));
- for (i = 0; i < inst->type_argc; ++i) {
- MonoType *t = inst->type_argv [i];
- ids [i] = add_type (prof, t);
- if (ids [i] == -1) {
- g_free (ids);
- return -1;
- }
- }
- id = prof->id ++;
- emit_record (prof, AOTPROF_RECORD_GINST, id);
- emit_int32 (prof, inst->type_argc);
- for (i = 0; i < inst->type_argc; ++i)
- emit_int32 (prof, ids [i]);
- g_free (ids);
-
- return id;
-}
-
-static int
-add_class (MonoProfiler *prof, MonoClass *klass)
-{
- int id, inst_id = -1, image_id;
- char *name;
-
- id = GPOINTER_TO_INT (g_hash_table_lookup (prof->classes, klass));
- if (id)
- return id - 1;
-
- image_id = add_image (prof, klass->image);
-
- if (mono_class_is_ginst (klass)) {
- MonoGenericContext *ctx = mono_class_get_context (klass);
- inst_id = add_ginst (prof, ctx->class_inst);
- if (inst_id == -1)
- return -1;
- }
-
- if (klass->nested_in)
- name = g_strdup_printf ("%s.%s/%s", klass->nested_in->name_space, klass->nested_in->name, klass->name);
- else
- name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
-
- id = prof->id ++;
- emit_record (prof, AOTPROF_RECORD_TYPE, id);
- emit_byte (prof, MONO_TYPE_CLASS);
- emit_int32 (prof, image_id);
- emit_int32 (prof, inst_id);
- emit_string (prof, name);
- g_free (name);
- g_hash_table_insert (prof->classes, klass, GINT_TO_POINTER (id + 1));
- return id;
-}
-
-static void
-add_method (MonoProfiler *prof, MonoMethod *m)
-{
- MonoError error;
- MonoMethodSignature *sig;
- char *s;
-
- sig = mono_method_signature_checked (m, &error);
- g_assert (mono_error_ok (&error));
-
- int class_id = add_class (prof, m->klass);
- if (class_id == -1)
- return;
- int inst_id = -1;
-
- if (m->is_inflated) {
- MonoGenericContext *ctx = mono_method_get_context (m);
- if (ctx->method_inst)
- inst_id = add_ginst (prof, ctx->method_inst);
- }
- int id = prof->id ++;
- emit_record (prof, AOTPROF_RECORD_METHOD, id);
- emit_int32 (prof, class_id);
- emit_int32 (prof, inst_id);
- emit_int32 (prof, sig->param_count);
- emit_string (prof, m->name);
- s = mono_signature_full_name (sig);
- emit_string (prof, s);
- g_free (s);
- if (verbose)
- printf ("%s %d\n", mono_method_full_name (m, 1), id);
-}
-
-/* called at the end of the program */
-static void
-prof_shutdown (MonoProfiler *prof)
-{
- FILE *outfile;
- int mindex;
- char magic [32];
-
- printf ("Creating output file: %s\n", prof->outfile_name);
-
- if (prof->outfile_name [0] == '#') {
- int fd = strtol (prof->outfile_name + 1, NULL, 10);
- outfile = fdopen (fd, "a");
- } else {
- outfile = fopen (prof->outfile_name, "w+");
- }
- if (!outfile) {
- fprintf (stderr, "Unable to create output file '%s': %s.\n", prof->outfile_name, strerror (errno));
- return;
- }
- prof->outfile = outfile;
-
- gint32 version = (AOT_PROFILER_MAJOR_VERSION << 16) | AOT_PROFILER_MINOR_VERSION;
- sprintf (magic, AOT_PROFILER_MAGIC);
- fwrite (magic, strlen (magic), 1, outfile);
- emit_int32 (prof, version);
-
- GHashTable *all_methods = g_hash_table_new (NULL, NULL);
- for (mindex = 0; mindex < prof->methods->len; ++mindex) {
- MonoMethod *m = (MonoMethod*)g_ptr_array_index (prof->methods, mindex);
-
- if (!mono_method_get_token (m))
- continue;
-
- if (g_hash_table_lookup (all_methods, m))
- continue;
- g_hash_table_insert (all_methods, m, m);
-
- add_method (prof, m);
- }
- emit_record (prof, AOTPROF_RECORD_NONE, 0);
-
- fclose (outfile);
-
- g_hash_table_destroy (all_methods);
- g_hash_table_destroy (prof->classes);
- g_hash_table_destroy (prof->images);
- g_ptr_array_free (prof->methods, TRUE);
- g_free (prof->outfile_name);
-}
+++ /dev/null
-#ifndef __MONO_PROFILER_AOT_H__
-#define __MONO_PROFILER_AOT_H__
-
-#include <config.h>
-
-/*
- * File format:
- * - magic
- * - major/minor version as an int, i.e. 0x00010001
- * - sequence of records terminated by a record with type TYPE_NONE
- * Record format:
- * - 1 byte record type (AotProfRecordType)
- * - 1 int record id
- * - record specific data
- * Encoding rules:
- * - int - 4 bytes little endian
- * - string - int length followed by data
- */
-
-typedef enum {
- AOTPROF_RECORD_NONE,
- AOTPROF_RECORD_IMAGE,
- AOTPROF_RECORD_TYPE,
- AOTPROF_RECORD_GINST,
- AOTPROF_RECORD_METHOD
-} AotProfRecordType;
-
-#define AOT_PROFILER_MAGIC "AOTPROFILE"
-
-#define AOT_PROFILER_MAJOR_VERSION 1
-#define AOT_PROFILER_MINOR_VERSION 0
-
-#endif /* __MONO_PROFILER_AOT_H__ */
+++ /dev/null
-/*
- * mono-profiler-iomap.c: IOMAP string profiler for Mono.
- *
- * Authors:
- * Marek Habersack <mhabersack@novell.com>
- *
- * Copyright (c) 2009 Novell, Inc (http://novell.com)
- *
- * Note: this profiler is completely unsafe wrt handling managed objects,
- * don't use and don't copy code from here.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#include "config.h"
-
-#include <string.h>
-#include <mono/utils/mono-io-portability.h>
-#include <mono/metadata/metadata.h>
-#include <mono/metadata/metadata-internals.h>
-#include <mono/metadata/class.h>
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/object-internals.h>
-#include <mono/metadata/image.h>
-#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/loader.h>
-#include <mono/utils/mono-os-mutex.h>
-
-#define LOCATION_INDENT " "
-#define BACKTRACE_SIZE 64
-
-typedef struct _MonoStackBacktraceInfo
-{
- MonoMethod *method;
- gint native_offset;
-} MonoStackBacktraceInfo;
-
-typedef struct
-{
- guint32 count;
- gchar *requestedName;
- gchar *actualName;
-} MismatchedFilesStats;
-
-typedef struct _SavedString
-{
- MonoString *string;
- MonoDomain *domain;
- void *stack [BACKTRACE_SIZE];
- gint stack_entries;
- struct _SavedString *next;
-} SavedString;
-
-typedef struct _SavedStringFindInfo
-{
- guint32 hash;
- size_t len;
-} SavedStringFindInfo;
-
-typedef struct _StringLocation
-{
- gchar *hint;
- struct _StringLocation *next;
-} StringLocation;
-
-struct _MonoProfiler
-{
- GHashTable *mismatched_files_hash;
- GHashTable *saved_strings_hash;
- GHashTable *string_locations_hash;
- gboolean may_have_locations;
-};
-
-typedef struct _StackWalkData
-{
- MonoProfiler *prof;
- void **stack;
- int stack_size;
- int frame_count;
-} StackWalkData;
-
-static mono_mutex_t mismatched_files_section;
-static gboolean runtime_initialized = FALSE;
-
-static inline void append_report (GString **report, const gchar *format, ...);
-static inline void print_report (const gchar *format, ...);
-static inline guint32 do_calc_string_hash (guint32 hash, const gchar *str);
-static inline guint32 calc_strings_hash (const gchar *str1, const gchar *str2, guint32 *str1hash);
-static void print_mismatched_stats (MonoProfiler *prof);
-static inline gchar *build_hint (SavedString *head);
-static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries);
-static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len);
-static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str);
-void mono_profiler_startup (const char *desc);
-
-static void mismatched_stats_foreach_func (gpointer key, gpointer value, gpointer user_data)
-{
- MismatchedFilesStats *stats = (MismatchedFilesStats*)value;
- StringLocation *location;
- MonoProfiler *prof = (MonoProfiler*)user_data;
- guint32 hash;
- gboolean bannerShown = FALSE;
-
- hash = do_calc_string_hash (0, stats->requestedName);
- fprintf (stdout,
- " Count: %u\n"
- "Requested: %s\n"
- " Actual: %s\n",
- stats->count, stats->requestedName, stats->actualName);
-
- if (!prof->may_have_locations) {
- fprintf (stdout, "\n");
- return;
- }
-
- location = (StringLocation *)g_hash_table_lookup (prof->string_locations_hash, &hash);
- while (location) {
- if (location->hint && strlen (location->hint) > 0) {
- if (!bannerShown) {
- fprintf (stdout, "Locations:\n");
- bannerShown = TRUE;
- }
- fprintf (stdout, "%s", location->hint);
- }
- location = location->next;
- if (location)
- fprintf (stdout, LOCATION_INDENT "--\n");
- }
-
- fprintf (stdout, "\n");
-}
-
-static void print_mismatched_stats (MonoProfiler *prof)
-{
- if (!prof->mismatched_files_hash || g_hash_table_size (prof->mismatched_files_hash) == 0)
- return;
-
- prof->may_have_locations = g_hash_table_size (prof->string_locations_hash) > 0;
-
- fprintf (stdout, "\n-=-=-=-=-=-=-= MONO_IOMAP Stats -=-=-=-=-=-=-=\n");
- g_hash_table_foreach (prof->mismatched_files_hash, mismatched_stats_foreach_func, (gpointer)prof);
- fflush (stdout);
-}
-
-static guint mismatched_files_guint32_hash (gconstpointer key)
-{
- if (!key)
- return 0;
-
- return *((guint32*)key);
-}
-
-static gboolean mismatched_files_guint32_equal (gconstpointer key1, gconstpointer key2)
-{
- if (!key1 || !key2)
- return FALSE;
-
- return (gboolean)(*((guint32*)key1) == *((guint32*)key2));
-}
-
-static inline guint32 do_calc_string_hash (guint32 hash, const gchar *str)
-{
- guint32 ret = hash;
- gchar *cc = (gchar*)str;
- gchar *end = (gchar*)(str + strlen (str) - 1);
-
- for (; cc < end; cc += 2) {
- ret = (ret << 5) - ret + *cc;
- ret = (ret << 5) - ret + cc [1];
- }
- end++;
- if (cc < end)
- ret = (ret << 5) - ret + *cc;
-
- return ret;
-}
-
-static inline guint32 calc_strings_hash (const gchar *str1, const gchar *str2, guint32 *str1hash)
-{
- guint32 hash = do_calc_string_hash (0, str1);
- if (str1hash)
- *str1hash = hash;
- return do_calc_string_hash (hash, str2);
-}
-
-static inline void print_report (const gchar *format, ...)
-{
- MonoError error;
- MonoClass *klass;
- MonoProperty *prop;
- MonoString *str;
- char *stack_trace;
- va_list ap;
-
- fprintf (stdout, "-=-=-=-=-=-=- MONO_IOMAP REPORT -=-=-=-=-=-=-\n");
- va_start (ap, format);
- vfprintf (stdout, format, ap);
- fprintf (stdout, "\n");
- va_end (ap);
- klass = mono_class_load_from_name (mono_get_corlib (), "System", "Environment");
- mono_class_init (klass);
- prop = mono_class_get_property_from_name (klass, "StackTrace");
- str = (MonoString*)mono_property_get_value_checked (prop, NULL, NULL, &error);
- mono_error_assert_ok (&error);
- stack_trace = mono_string_to_utf8_checked (str, &error);
- mono_error_assert_ok (&error);
-
- fprintf (stdout, "-= Stack Trace =-\n%s\n\n", stack_trace);
- g_free (stack_trace);
- fflush (stdout);
-}
-
-static inline void append_report (GString **report, const gchar *format, ...)
-{
- va_list ap;
- if (!*report)
- *report = g_string_new ("");
-
- va_start (ap, format);
- g_string_append_vprintf (*report, format, ap);
- va_end (ap);
-}
-
-static gboolean saved_strings_find_func (gpointer key, gpointer value, gpointer user_data)
-{
- MonoError error;
- SavedStringFindInfo *info = (SavedStringFindInfo*)user_data;
- SavedString *saved = (SavedString*)value;
- gchar *utf_str;
- guint32 hash;
-
- if (!info || !saved || mono_string_length (saved->string) != info->len)
- return FALSE;
-
- utf_str = mono_string_to_utf8_checked (saved->string, &error);
- mono_error_assert_ok (&error);
- hash = do_calc_string_hash (0, utf_str);
- g_free (utf_str);
-
- if (hash != info->hash)
- return FALSE;
-
- return TRUE;
-}
-
-static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len)
-{
- StringLocation *location = (StringLocation *)g_hash_table_lookup (prof->string_locations_hash, &hash);
- SavedString *saved;
- SavedStringFindInfo info;
- guint32 *hashptr;
-
- if (location)
- return;
-
- info.hash = hash;
- info.len = len;
-
- /* Expensive but unavoidable... */
- saved = (SavedString*)g_hash_table_find (prof->saved_strings_hash, saved_strings_find_func, &info);
- hashptr = (guint32*)g_malloc (sizeof (guint32));
- *hashptr = hash;
- location = (StringLocation*)g_malloc0 (sizeof (location));
-
- g_hash_table_insert (prof->string_locations_hash, hashptr, location);
- if (!saved)
- return;
-
- g_hash_table_remove (prof->saved_strings_hash, saved->string);
- location->hint = build_hint (saved);
-}
-
-static gboolean ignore_frame (MonoMethod *method)
-{
- MonoClass *klass = method->klass;
-
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- return TRUE;
-
- /* Now ignore the assemblies we know shouldn't contain mixed-case names (only the most frequent cases) */
- if (klass->image ) {
- if (strcmp (klass->image->assembly_name, "mscorlib") == 0)
- return TRUE;
- else if (strcmp (klass->image->assembly_name, "System") == 0)
- return TRUE;
- else if (strncmp (klass->image->assembly_name, "Mono.", 5) == 0)
- return TRUE;
- else if (strncmp (klass->image->assembly_name, "System.", 7) == 0)
- return TRUE;
- else if (strcmp (klass->image->assembly_name, "PEAPI") == 0)
- return TRUE;
- }
-
- return FALSE;
-}
-
-static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries)
-{
- gchar *hint;
- MonoMethod *method, *selectedMethod;
- MonoAssembly *assembly;
- MonoImage *image;
- MonoDebugSourceLocation *location;
- MonoStackBacktraceInfo *info;
- gboolean use_full_trace;
- char *methodName;
- gint i, native_offset, firstAvailable;
-
- selectedMethod = NULL;
- firstAvailable = -1;
- use_full_trace = FALSE;
- native_offset = -1;
- for (i = 0; i < stack_entries; i++) {
- info = (MonoStackBacktraceInfo*) stack [i];
- method = info ? info->method : NULL;
-
- if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
- continue;
-
- if (firstAvailable == -1)
- firstAvailable = i;
-
- image = method->klass->image;
- assembly = image->assembly;
-
- if ((assembly && assembly->in_gac) || ignore_frame (method))
- continue;
- selectedMethod = method;
- native_offset = info->native_offset;
- break;
- }
-
- if (!selectedMethod) {
- /* All the frames were from assemblies installed in GAC. Find first frame that is
- * not in the ignore list */
- for (i = 0; i < stack_entries; i++) {
- info = (MonoStackBacktraceInfo*) stack [i];
- method = info ? info->method : NULL;
-
- if (!method || ignore_frame (method))
- continue;
- selectedMethod = method;
- native_offset = info->native_offset;
- break;
- }
-
- if (!selectedMethod)
- use_full_trace = TRUE;
- }
-
- hint = NULL;
- if (use_full_trace) {
- GString *trace = g_string_new ("Full trace:\n");
- for (i = firstAvailable; i < stack_entries; i++) {
- info = (MonoStackBacktraceInfo*) stack [i];
- method = info ? info->method : NULL;
- if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
- continue;
-
- location = mono_debug_lookup_source_location (method, info->native_offset, domain);
- methodName = mono_method_full_name (method, TRUE);
-
- if (location) {
- append_report (&trace, LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
- mono_debug_free_source_location (location);
- } else
- append_report (&trace, LOCATION_INDENT "%s\n", methodName);
- g_free (methodName);
- }
-
- if (trace) {
- if (trace->len)
- hint = g_string_free (trace, FALSE);
- else
- g_string_free (trace, TRUE);
- }
- } else {
- location = mono_debug_lookup_source_location (selectedMethod, native_offset, domain);
- methodName = mono_method_full_name (selectedMethod, TRUE);
-
- if (location) {
- hint = g_strdup_printf (LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
- mono_debug_free_source_location (location);
- } else
- hint = g_strdup_printf (LOCATION_INDENT "%s\n", methodName);
- g_free (methodName);
- }
-
- return hint;
-}
-
-static inline gchar *build_hint (SavedString *head)
-{
- SavedString *current;
- gchar *tmp;
- GString *hint = NULL;
-
- current = head;
- while (current) {
- tmp = build_hint_from_stack (current->domain, current->stack, current->stack_entries);
- current = current->next;
- if (!tmp)
- continue;
-
- append_report (&hint, tmp);
- }
-
- if (hint) {
- if (hint->len)
- return g_string_free (hint, FALSE);
- else {
- g_string_free (hint, FALSE);
- return NULL;
- }
- }
-
- return NULL;
-}
-
-static gboolean stack_walk_func (MonoMethod *method, gint32 native_offset, gint32 il_offset, gboolean managed, gpointer data)
-{
- StackWalkData *swdata = (StackWalkData*)data;
- MonoStackBacktraceInfo *info;
-
- if (swdata->frame_count >= swdata->stack_size)
- return TRUE;
-
- info = (MonoStackBacktraceInfo*)g_malloc (sizeof (*info));
- info->method = method;
- info->native_offset = native_offset;
-
- swdata->stack [swdata->frame_count++] = info;
- return FALSE;
-}
-
-static inline int mono_stack_backtrace (MonoProfiler *prof, MonoDomain *domain, void **stack, int size)
-{
- StackWalkData data;
-
- data.prof = prof;
- data.stack = stack;
- data.stack_size = size;
- data.frame_count = 0;
-
- mono_stack_walk_no_il (stack_walk_func, (gpointer)&data);
-
- return data.frame_count;
-}
-
-static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str)
-{
- SavedString *head, *entry;
-
- if (!str || !domain || !runtime_initialized)
- return;
-
- entry = (SavedString*)g_malloc0 (sizeof (SavedString));
- entry->string = str;
- entry->domain = domain;
- entry->stack_entries = mono_stack_backtrace (prof, domain, entry->stack, BACKTRACE_SIZE);
- if (entry->stack_entries == 0) {
- g_free (entry);
- return;
- }
-
- mono_os_mutex_lock (&mismatched_files_section);
- head = (SavedString*)g_hash_table_lookup (prof->saved_strings_hash, (gpointer)str);
- if (head) {
- while (head->next)
- head = head->next;
- head->next = entry;
- } else
- g_hash_table_insert (prof->saved_strings_hash, (gpointer)str, (gpointer)entry);
- mono_os_mutex_unlock (&mismatched_files_section);
-}
-
-static MonoClass *string_class = NULL;
-
-static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
-{
- if (klass != string_class)
- return;
- mono_portability_remember_string (prof, mono_object_get_domain (obj), (MonoString*)obj);
-}
-
-static void mono_portability_iomap_event (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname)
-{
- guint32 hash, pathnameHash;
- MismatchedFilesStats *stats;
-
- if (!runtime_initialized)
- return;
-
- mono_os_mutex_lock (&mismatched_files_section);
- hash = calc_strings_hash (pathname, new_pathname, &pathnameHash);
- stats = (MismatchedFilesStats*)g_hash_table_lookup (prof->mismatched_files_hash, &hash);
- if (stats == NULL) {
- guint32 *hashptr;
-
- stats = (MismatchedFilesStats*) g_malloc (sizeof (MismatchedFilesStats));
- stats->count = 1;
- stats->requestedName = g_strdup (pathname);
- stats->actualName = g_strdup (new_pathname);
- hashptr = (guint32*)g_malloc (sizeof (guint32));
- if (hashptr) {
- *hashptr = hash;
- g_hash_table_insert (prof->mismatched_files_hash, (gpointer)hashptr, stats);
- } else
- g_error ("Out of memory allocating integer pointer for mismatched files hash table.");
-
- store_string_location (prof, (const gchar*)stats->requestedName, pathnameHash, strlen (stats->requestedName));
- mono_os_mutex_unlock (&mismatched_files_section);
-
- print_report ("%s - Found file path: '%s'\n", report, new_pathname);
- } else {
- mono_os_mutex_unlock (&mismatched_files_section);
- stats->count++;
- }
-}
-
-static void runtime_initialized_cb (MonoProfiler *prof)
-{
- runtime_initialized = TRUE;
- string_class = mono_get_string_class ();
-}
-
-static void profiler_shutdown (MonoProfiler *prof)
-{
- print_mismatched_stats (prof);
- mono_os_mutex_destroy (&mismatched_files_section);
-}
-
-void mono_profiler_startup (const char *desc)
-{
- MonoProfiler *prof = g_new0 (MonoProfiler, 1);
-
- mono_os_mutex_init (&mismatched_files_section);
- prof->mismatched_files_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
- prof->saved_strings_hash = g_hash_table_new (NULL, NULL);
- prof->string_locations_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
-
- mono_profiler_install (prof, profiler_shutdown);
- mono_profiler_install_runtime_initialized (runtime_initialized_cb);
- mono_profiler_install_iomap (mono_portability_iomap_event);
- mono_profiler_install_allocation (mono_portability_remember_alloc);
-
- mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_IOMAP_EVENTS));
-}
+++ /dev/null
-/*
- * mono-profiler-log.c: mono log profiler
- *
- * Authors:
- * Paolo Molaro (lupus@ximian.com)
- * Alex Rønne Petersen (alexrp@xamarin.com)
- *
- * Copyright 2010 Novell, Inc (http://www.novell.com)
- * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/debug-helpers.h>
-#include "../metadata/metadata-internals.h"
-#include <mono/metadata/mono-config.h>
-#include <mono/metadata/mono-gc.h>
-#include <mono/metadata/mono-perfcounters.h>
-#include <mono/metadata/profiler.h>
-#include <mono/utils/atomic.h>
-#include <mono/utils/hazard-pointer.h>
-#include <mono/utils/lock-free-alloc.h>
-#include <mono/utils/lock-free-queue.h>
-#include <mono/utils/mono-conc-hashtable.h>
-#include <mono/utils/mono-counters.h>
-#include <mono/utils/mono-linked-list-set.h>
-#include <mono/utils/mono-membar.h>
-#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-os-mutex.h>
-#include <mono/utils/mono-os-semaphore.h>
-#include <mono/utils/mono-threads.h>
-#include <mono/utils/mono-threads-api.h>
-#include "mono-profiler-log.h"
-
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_LINK_H
-#include <link.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(__APPLE__)
-#include <mach/mach_time.h>
-#endif
-#include <netinet/in.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#include <sys/socket.h>
-#if defined (HAVE_SYS_ZLIB)
-#include <zlib.h>
-#endif
-
-#ifdef HAVE_SCHED_GETAFFINITY
-# ifndef GLIBC_HAS_CPU_COUNT
-static int
-CPU_COUNT(cpu_set_t *set)
-{
- int i, count = 0;
-
- for (int i = 0; i < CPU_SETSIZE; i++)
- if (CPU_ISSET(i, set))
- count++;
- return count;
-}
-# endif
-#endif
-
-#define BUFFER_SIZE (4096 * 16)
-
-/* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
-#define LEB128_SIZE 10
-
-/* Size of a value encoded as a single byte. */
-#undef BYTE_SIZE // mach/i386/vm_param.h on OS X defines this to 8, but it isn't used for anything.
-#define BYTE_SIZE 1
-
-/* Size in bytes of the event prefix (ID + time). */
-#define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
-
-static volatile gint32 runtime_inited;
-static volatile gint32 in_shutdown;
-
-static gboolean no_counters;
-static int nocalls = 0;
-static int notraces = 0;
-static int use_zip = 0;
-static int do_report = 0;
-static int do_heap_shot = 0;
-static int max_call_depth = 100;
-static int command_port = 0;
-static int heapshot_requested = 0;
-static int sample_freq = 0;
-static int do_mono_sample = 0;
-static int do_debug = 0;
-static int do_coverage = 0;
-static gboolean only_coverage;
-static gboolean debug_coverage = FALSE;
-static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
-static int max_allocated_sample_hits;
-
-// Statistics for internal profiler data structures.
-static gint32 sample_allocations_ctr,
- buffer_allocations_ctr;
-
-// Statistics for profiler events.
-static gint32 sync_points_ctr,
- heap_objects_ctr,
- heap_starts_ctr,
- heap_ends_ctr,
- heap_roots_ctr,
- gc_events_ctr,
- gc_resizes_ctr,
- gc_allocs_ctr,
- gc_moves_ctr,
- gc_handle_creations_ctr,
- gc_handle_deletions_ctr,
- finalize_begins_ctr,
- finalize_ends_ctr,
- finalize_object_begins_ctr,
- finalize_object_ends_ctr,
- image_loads_ctr,
- image_unloads_ctr,
- assembly_loads_ctr,
- assembly_unloads_ctr,
- class_loads_ctr,
- class_unloads_ctr,
- method_entries_ctr,
- method_exits_ctr,
- method_exception_exits_ctr,
- method_jits_ctr,
- code_buffers_ctr,
- exception_throws_ctr,
- exception_clauses_ctr,
- monitor_contentions_ctr,
- monitor_acquisitions_ctr,
- monitor_failures_ctr,
- thread_starts_ctr,
- thread_ends_ctr,
- thread_names_ctr,
- domain_loads_ctr,
- domain_unloads_ctr,
- domain_names_ctr,
- context_loads_ctr,
- context_unloads_ctr,
- sample_ubins_ctr,
- sample_usyms_ctr,
- sample_hits_ctr,
- counter_descriptors_ctr,
- counter_samples_ctr,
- perfcounter_descriptors_ctr,
- perfcounter_samples_ctr,
- coverage_methods_ctr,
- coverage_statements_ctr,
- coverage_classes_ctr,
- coverage_assemblies_ctr;
-
-static MonoLinkedListSet profiler_thread_list;
-
-/*
- * file format:
- * [header] [buffer]*
- *
- * The file is composed by a header followed by 0 or more buffers.
- * Each buffer contains events that happened on a thread: for a given thread
- * buffers that appear later in the file are guaranteed to contain events
- * that happened later in time. Buffers from separate threads could be interleaved,
- * though.
- * Buffers are not required to be aligned.
- *
- * header format:
- * [id: 4 bytes] constant value: LOG_HEADER_ID
- * [major: 1 byte] [minor: 1 byte] major and minor version of the log profiler
- * [format: 1 byte] version of the data format for the rest of the file
- * [ptrsize: 1 byte] size in bytes of a pointer in the profiled program
- * [startup time: 8 bytes] time in milliseconds since the unix epoch when the program started
- * [timer overhead: 4 bytes] approximate overhead in nanoseconds of the timer
- * [flags: 4 bytes] file format flags, should be 0 for now
- * [pid: 4 bytes] pid of the profiled process
- * [port: 2 bytes] tcp port for server if != 0
- * [args size: 4 bytes] size of args
- * [args: string] arguments passed to the profiler
- * [arch size: 4 bytes] size of arch
- * [arch: string] architecture the profiler is running on
- * [os size: 4 bytes] size of os
- * [os: string] operating system the profiler is running on
- *
- * The multiple byte integers are in little-endian format.
- *
- * buffer format:
- * [buffer header] [event]*
- * Buffers have a fixed-size header followed by 0 or more bytes of event data.
- * Timing information and other values in the event data are usually stored
- * as uleb128 or sleb128 integers. To save space, as noted for each item below,
- * some data is represented as a difference between the actual value and
- * either the last value of the same type (like for timing information) or
- * as the difference from a value stored in a buffer header.
- *
- * For timing information the data is stored as uleb128, since timing
- * increases in a monotonic way in each thread: the value is the number of
- * nanoseconds to add to the last seen timing data in a buffer. The first value
- * in a buffer will be calculated from the time_base field in the buffer head.
- *
- * Object or heap sizes are stored as uleb128.
- * Pointer differences are stored as sleb128, instead.
- *
- * If an unexpected value is found, the rest of the buffer should be ignored,
- * as generally the later values need the former to be interpreted correctly.
- *
- * buffer header format:
- * [bufid: 4 bytes] constant value: BUF_ID
- * [len: 4 bytes] size of the data following the buffer header
- * [time_base: 8 bytes] time base in nanoseconds since an unspecified epoch
- * [ptr_base: 8 bytes] base value for pointers
- * [obj_base: 8 bytes] base value for object addresses
- * [thread id: 8 bytes] system-specific thread ID (pthread_t for example)
- * [method_base: 8 bytes] base value for MonoMethod pointers
- *
- * event format:
- * [extended info: upper 4 bits] [type: lower 4 bits]
- * [time diff: uleb128] nanoseconds since last timing
- * [data]*
- * The data that follows depends on type and the extended info.
- * Type is one of the enum values in mono-profiler-log.h: TYPE_ALLOC, TYPE_GC,
- * TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
- * The extended info bits are interpreted based on type, see
- * each individual event description below.
- * strings are represented as a 0-terminated utf8 sequence.
- *
- * backtrace format:
- * [num: uleb128] number of frames following
- * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base
- *
- * type alloc format:
- * type: TYPE_ALLOC
- * exinfo: flags: TYPE_ALLOC_BT
- * [ptr: sleb128] class as a byte difference from ptr_base
- * [obj: sleb128] object address as a byte difference from obj_base
- * [size: uleb128] size of the object in the heap
- * If the TYPE_ALLOC_BT flag is set, a backtrace follows.
- *
- * type GC format:
- * type: TYPE_GC
- * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
- * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
- * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
- * if exinfo == TYPE_GC_RESIZE
- * [heap_size: uleb128] new heap size
- * if exinfo == TYPE_GC_EVENT
- * [event type: byte] GC event (MONO_GC_EVENT_* from profiler.h)
- * [generation: byte] GC generation event refers to
- * if exinfo == TYPE_GC_MOVE
- * [num_objects: uleb128] number of object moves that follow
- * [objaddr: sleb128]+ num_objects object pointer differences from obj_base
- * num is always an even number: the even items are the old
- * addresses, the odd numbers are the respective new object addresses
- * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
- * [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
- * upper bits reserved as flags
- * [handle: uleb128] GC handle value
- * [objaddr: sleb128] object pointer differences from obj_base
- * If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
- * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
- * [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
- * upper bits reserved as flags
- * [handle: uleb128] GC handle value
- * If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
- * if exinfo == TYPE_GC_FINALIZE_OBJECT_{START,END}
- * [object: sleb128] the object as a difference from obj_base
- *
- * type metadata format:
- * type: TYPE_METADATA
- * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN)
- * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
- * TYPE_THREAD, TYPE_CONTEXT
- * [pointer: sleb128] pointer of the metadata type depending on mtype
- * if mtype == TYPE_CLASS
- * [image: sleb128] MonoImage* as a pointer difference from ptr_base
- * [name: string] full class name
- * if mtype == TYPE_IMAGE
- * [name: string] image file name
- * if mtype == TYPE_ASSEMBLY
- * [name: string] assembly name
- * if mtype == TYPE_DOMAIN && exinfo == 0
- * [name: string] domain friendly name
- * if mtype == TYPE_CONTEXT
- * [domain: sleb128] domain id as pointer
- * if mtype == TYPE_THREAD && exinfo == 0
- * [name: string] thread name
- *
- * type method format:
- * type: TYPE_METHOD
- * exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
- * [method: sleb128] MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base
- * if exinfo == TYPE_JIT
- * [code address: sleb128] pointer to the native code as a diff from ptr_base
- * [code size: uleb128] size of the generated code
- * [name: string] full method name
- *
- * type exception format:
- * type: TYPE_EXCEPTION
- * exinfo: TYPE_THROW_BT flag or one of: TYPE_CLAUSE
- * if exinfo == TYPE_CLAUSE
- * [clause type: byte] MonoExceptionEnum enum value
- * [clause index: uleb128] index of the current clause
- * [method: sleb128] MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base
- * else
- * [object: sleb128] the exception object as a difference from obj_base
- * if exinfo has TYPE_THROW_BT set, a backtrace follows.
- *
- * type runtime format:
- * type: TYPE_RUNTIME
- * exinfo: one of: TYPE_JITHELPER
- * if exinfo == TYPE_JITHELPER
- * [type: byte] MonoProfilerCodeBufferType enum value
- * [buffer address: sleb128] pointer to the native code as a diff from ptr_base
- * [buffer size: uleb128] size of the generated code
- * if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
- * [name: string] buffer description name
- *
- * type monitor format:
- * type: TYPE_MONITOR
- * exinfo: TYPE_MONITOR_BT flag and one of: MONO_PROFILER_MONITOR_(CONTENTION|FAIL|DONE)
- * [object: sleb128] the lock object as a difference from obj_base
- * if exinfo.low3bits == MONO_PROFILER_MONITOR_CONTENTION
- * If the TYPE_MONITOR_BT flag is set, a backtrace follows.
- *
- * type heap format
- * type: TYPE_HEAP
- * exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
- * if exinfo == TYPE_HEAP_OBJECT
- * [object: sleb128] the object as a difference from obj_base
- * [class: sleb128] the object MonoClass* as a difference from ptr_base
- * [size: uleb128] size of the object on the heap
- * [num_refs: uleb128] number of object references
- * each referenced objref is preceded by a uleb128 encoded offset: the
- * first offset is from the object address and each next offset is relative
- * to the previous one
- * [objrefs: sleb128]+ object referenced as a difference from obj_base
- * The same object can appear multiple times, but only the first time
- * with size != 0: in the other cases this data will only be used to
- * provide additional referenced objects.
- * if exinfo == TYPE_HEAP_ROOT
- * [num_roots: uleb128] number of root references
- * [num_gc: uleb128] number of major gcs
- * [object: sleb128] the object as a difference from obj_base
- * [root_type: byte] the root_type: MonoProfileGCRootType (profiler.h)
- * [extra_info: uleb128] the extra_info value
- * object, root_type and extra_info are repeated num_roots times
- *
- * type sample format
- * type: TYPE_SAMPLE
- * exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
- * if exinfo == TYPE_SAMPLE_HIT
- * [thread: sleb128] thread id as difference from ptr_base
- * [count: uleb128] number of following instruction addresses
- * [ip: sleb128]* instruction pointer as difference from ptr_base
- * [mbt_count: uleb128] number of managed backtrace frames
- * [method: sleb128]* MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
- * if exinfo == TYPE_SAMPLE_USYM
- * [address: sleb128] symbol address as a difference from ptr_base
- * [size: uleb128] symbol size (may be 0 if unknown)
- * [name: string] symbol name
- * if exinfo == TYPE_SAMPLE_UBIN
- * [address: sleb128] address where binary has been loaded
- * [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
- * [size: uleb128] memory size
- * [name: string] binary name
- * if exinfo == TYPE_SAMPLE_COUNTERS_DESC
- * [len: uleb128] number of counters
- * for i = 0 to len
- * [section: uleb128] section of counter
- * if section == MONO_COUNTER_PERFCOUNTERS:
- * [section_name: string] section name of counter
- * [name: string] name of counter
- * [type: byte] type of counter
- * [unit: byte] unit of counter
- * [variance: byte] variance of counter
- * [index: uleb128] unique index of counter
- * if exinfo == TYPE_SAMPLE_COUNTERS
- * while true:
- * [index: uleb128] unique index of counter
- * if index == 0:
- * break
- * [type: byte] type of counter value
- * if type == string:
- * if value == null:
- * [0: uleb128] 0 -> value is null
- * else:
- * [1: uleb128] 1 -> value is not null
- * [value: string] counter value
- * else:
- * [value: uleb128/sleb128/double] counter value, can be sleb128, uleb128 or double (determined by using type)
- *
- * type coverage format
- * type: TYPE_COVERAGE
- * exinfo: one of TYPE_COVERAGE_METHOD, TYPE_COVERAGE_STATEMENT, TYPE_COVERAGE_ASSEMBLY, TYPE_COVERAGE_CLASS
- * if exinfo == TYPE_COVERAGE_METHOD
- * [assembly: string] name of assembly
- * [class: string] name of the class
- * [name: string] name of the method
- * [signature: string] the signature of the method
- * [filename: string] the file path of the file that contains this method
- * [token: uleb128] the method token
- * [method_id: uleb128] an ID for this data to associate with the buffers of TYPE_COVERAGE_STATEMENTS
- * [len: uleb128] the number of TYPE_COVERAGE_BUFFERS associated with this method
- * if exinfo == TYPE_COVERAGE_STATEMENTS
- * [method_id: uleb128] an the TYPE_COVERAGE_METHOD buffer to associate this with
- * [offset: uleb128] the il offset relative to the previous offset
- * [counter: uleb128] the counter for this instruction
- * [line: uleb128] the line of filename containing this instruction
- * [column: uleb128] the column containing this instruction
- * if exinfo == TYPE_COVERAGE_ASSEMBLY
- * [name: string] assembly name
- * [guid: string] assembly GUID
- * [filename: string] assembly filename
- * [number_of_methods: uleb128] the number of methods in this assembly
- * [fully_covered: uleb128] the number of fully covered methods
- * [partially_covered: uleb128] the number of partially covered methods
- * currently partially_covered will always be 0, and fully_covered is the
- * number of methods that are fully and partially covered.
- * if exinfo == TYPE_COVERAGE_CLASS
- * [name: string] assembly name
- * [class: string] class name
- * [number_of_methods: uleb128] the number of methods in this class
- * [fully_covered: uleb128] the number of fully covered methods
- * [partially_covered: uleb128] the number of partially covered methods
- * currently partially_covered will always be 0, and fully_covered is the
- * number of methods that are fully and partially covered.
- *
- * type meta format:
- * type: TYPE_META
- * exinfo: one of: TYPE_SYNC_POINT
- * if exinfo == TYPE_SYNC_POINT
- * [type: byte] MonoProfilerSyncPointType enum value
- */
-
-// Pending data to be written to the log, for a single thread.
-// Threads periodically flush their own LogBuffers by calling safe_send
-typedef struct _LogBuffer LogBuffer;
-struct _LogBuffer {
- // Next (older) LogBuffer in processing queue
- LogBuffer *next;
-
- uint64_t time_base;
- uint64_t last_time;
- uintptr_t ptr_base;
- uintptr_t method_base;
- uintptr_t last_method;
- uintptr_t obj_base;
- uintptr_t thread_id;
-
- // Bytes allocated for this LogBuffer
- int size;
-
- // Start of currently unused space in buffer
- unsigned char* cursor;
-
- // Pointer to start-of-structure-plus-size (for convenience)
- unsigned char* buf_end;
-
- // Start of data in buffer. Contents follow "buffer format" described above.
- unsigned char buf [1];
-};
-
-typedef struct {
- MonoLinkedListSetNode node;
-
- // Convenience pointer to the profiler structure.
- MonoProfiler *profiler;
-
- // Was this thread added to the LLS?
- gboolean attached;
-
- // The current log buffer for this thread.
- LogBuffer *buffer;
-
- // Methods referenced by events in `buffer`, see `MethodInfo`.
- GPtrArray *methods;
-
- // Current call depth for enter/leave events.
- int call_depth;
-
- // Indicates whether this thread is currently writing to its `buffer`.
- gboolean busy;
-
- // Has this thread written a thread end event to `buffer`?
- gboolean ended;
-} MonoProfilerThread;
-
-static uintptr_t
-thread_id (void)
-{
- return (uintptr_t) mono_native_thread_id_get ();
-}
-
-static uintptr_t
-process_id (void)
-{
-#ifdef HOST_WIN32
- return (uintptr_t) GetCurrentProcessId ();
-#else
- return (uintptr_t) getpid ();
-#endif
-}
-
-#ifdef __APPLE__
-static mach_timebase_info_data_t timebase_info;
-#elif defined (HOST_WIN32)
-static LARGE_INTEGER pcounter_freq;
-#endif
-
-#define TICKS_PER_SEC 1000000000LL
-
-static uint64_t
-current_time (void)
-{
-#ifdef __APPLE__
- uint64_t time = mach_absolute_time ();
-
- time *= timebase_info.numer;
- time /= timebase_info.denom;
-
- return time;
-#elif defined (HOST_WIN32)
- LARGE_INTEGER value;
-
- QueryPerformanceCounter (&value);
-
- return value.QuadPart * TICKS_PER_SEC / pcounter_freq.QuadPart;
-#elif defined (CLOCK_MONOTONIC)
- struct timespec tspec;
-
- clock_gettime (CLOCK_MONOTONIC, &tspec);
-
- return ((uint64_t) tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec);
-#else
- struct timeval tv;
-
- gettimeofday (&tv, NULL);
-
- return ((uint64_t) tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000);
-#endif
-}
-
-static int timer_overhead;
-
-static void
-init_time (void)
-{
-#ifdef __APPLE__
- mach_timebase_info (&timebase_info);
-#elif defined (HOST_WIN32)
- QueryPerformanceFrequency (&pcounter_freq);
-#endif
-
- uint64_t time_start = current_time ();
-
- for (int i = 0; i < 256; ++i)
- current_time ();
-
- uint64_t time_end = current_time ();
-
- timer_overhead = (time_end - time_start) / 256;
-}
-
-/*
- * These macros should be used when writing an event to a log buffer. They take
- * care of a bunch of stuff that can be repetitive and error-prone, such as
- * acquiring/releasing the buffer lock, incrementing the event counter,
- * expanding the log buffer, processing requests, etc. They also create a scope
- * so that it's harder to leak the LogBuffer pointer, which can be problematic
- * as the pointer is unstable when the buffer lock isn't acquired.
- */
-
-#define ENTER_LOG(COUNTER, BUFFER, SIZE) \
- do { \
- MonoProfilerThread *thread__ = PROF_TLS_GET (); \
- if (thread__->attached) \
- buffer_lock (); \
- g_assert (!thread__->busy && "Why are we trying to write a new event while already writing one?"); \
- thread__->busy = TRUE; \
- InterlockedIncrement ((COUNTER)); \
- LogBuffer *BUFFER = ensure_logbuf_unsafe (thread__, (SIZE))
-
-#define EXIT_LOG_EXPLICIT(SEND, REQUESTS) \
- thread__->busy = FALSE; \
- if ((SEND)) \
- send_log_unsafe (TRUE); \
- if (thread__->attached) \
- buffer_unlock (); \
- if ((REQUESTS)) \
- process_requests (); \
- } while (0)
-
-// Pass these to EXIT_LOG_EXPLICIT () for easier reading.
-#define DO_SEND TRUE
-#define NO_SEND FALSE
-#define DO_REQUESTS TRUE
-#define NO_REQUESTS FALSE
-
-#define EXIT_LOG EXIT_LOG_EXPLICIT (DO_SEND, DO_REQUESTS)
-
-static volatile gint32 buffer_rwlock_count;
-static volatile gpointer buffer_rwlock_exclusive;
-
-// Can be used recursively.
-static void
-buffer_lock (void)
-{
- /*
- * If the thread holding the exclusive lock tries to modify the
- * reader count, just make it a no-op. This way, we also avoid
- * invoking the GC safe point macros below, which could break if
- * done from a thread that is currently the initiator of STW.
- *
- * In other words, we rely on the fact that the GC thread takes
- * the exclusive lock in the gc_event () callback when the world
- * is about to stop.
- */
- if (InterlockedReadPointer (&buffer_rwlock_exclusive) != (gpointer) thread_id ()) {
- MONO_ENTER_GC_SAFE;
-
- while (InterlockedReadPointer (&buffer_rwlock_exclusive))
- mono_thread_info_yield ();
-
- InterlockedIncrement (&buffer_rwlock_count);
-
- MONO_EXIT_GC_SAFE;
- }
-
- mono_memory_barrier ();
-}
-
-static void
-buffer_unlock (void)
-{
- mono_memory_barrier ();
-
- // See the comment in buffer_lock ().
- if (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id ())
- return;
-
- g_assert (InterlockedRead (&buffer_rwlock_count) && "Why are we trying to decrement a zero reader count?");
-
- InterlockedDecrement (&buffer_rwlock_count);
-}
-
-// Cannot be used recursively.
-static void
-buffer_lock_excl (void)
-{
- gpointer tid = (gpointer) thread_id ();
-
- g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) != tid && "Why are we taking the exclusive lock twice?");
-
- MONO_ENTER_GC_SAFE;
-
- while (InterlockedCompareExchangePointer (&buffer_rwlock_exclusive, tid, 0))
- mono_thread_info_yield ();
-
- while (InterlockedRead (&buffer_rwlock_count))
- mono_thread_info_yield ();
-
- MONO_EXIT_GC_SAFE;
-
- mono_memory_barrier ();
-}
-
-static void
-buffer_unlock_excl (void)
-{
- mono_memory_barrier ();
-
- g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why is the exclusive lock not held?");
- g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why does another thread hold the exclusive lock?");
- g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why are there readers when the exclusive lock is held?");
-
- InterlockedWritePointer (&buffer_rwlock_exclusive, NULL);
-}
-
-typedef struct _BinaryObject BinaryObject;
-struct _BinaryObject {
- BinaryObject *next;
- void *addr;
- char *name;
-};
-
-struct _MonoProfiler {
- FILE* file;
-#if defined (HAVE_SYS_ZLIB)
- gzFile gzfile;
-#endif
- char *args;
- uint64_t startup_time;
- int pipe_output;
- int command_port;
- int server_socket;
- int pipes [2];
- MonoNativeThreadId helper_thread;
- MonoNativeThreadId writer_thread;
- MonoNativeThreadId dumper_thread;
- volatile gint32 run_writer_thread;
- MonoLockFreeAllocSizeClass writer_entry_size_class;
- MonoLockFreeAllocator writer_entry_allocator;
- MonoLockFreeQueue writer_queue;
- MonoSemType writer_queue_sem;
- MonoConcurrentHashTable *method_table;
- mono_mutex_t method_table_mutex;
- volatile gint32 run_dumper_thread;
- MonoLockFreeQueue dumper_queue;
- MonoSemType dumper_queue_sem;
- MonoLockFreeAllocSizeClass sample_size_class;
- MonoLockFreeAllocator sample_allocator;
- MonoLockFreeQueue sample_reuse_queue;
- BinaryObject *binary_objects;
- GPtrArray *coverage_filters;
-};
-
-typedef struct {
- MonoLockFreeQueueNode node;
- GPtrArray *methods;
- LogBuffer *buffer;
-} WriterQueueEntry;
-
-#define WRITER_ENTRY_BLOCK_SIZE (mono_pagesize ())
-
-typedef struct {
- MonoMethod *method;
- MonoJitInfo *ji;
- uint64_t time;
-} MethodInfo;
-
-#ifdef HOST_WIN32
-
-#define PROF_TLS_SET(VAL) (TlsSetValue (profiler_tls, (VAL)))
-#define PROF_TLS_GET() ((MonoProfilerThread *) TlsGetValue (profiler_tls))
-#define PROF_TLS_INIT() (profiler_tls = TlsAlloc ())
-#define PROF_TLS_FREE() (TlsFree (profiler_tls))
-
-static DWORD profiler_tls;
-
-#elif HAVE_KW_THREAD
-
-#define PROF_TLS_SET(VAL) (profiler_tls = (VAL))
-#define PROF_TLS_GET() (profiler_tls)
-#define PROF_TLS_INIT()
-#define PROF_TLS_FREE()
-
-static __thread MonoProfilerThread *profiler_tls;
-
-#else
-
-#define PROF_TLS_SET(VAL) (pthread_setspecific (profiler_tls, (VAL)))
-#define PROF_TLS_GET() ((MonoProfilerThread *) pthread_getspecific (profiler_tls))
-#define PROF_TLS_INIT() (pthread_key_create (&profiler_tls, NULL))
-#define PROF_TLS_FREE() (pthread_key_delete (profiler_tls))
-
-static pthread_key_t profiler_tls;
-
-#endif
-
-static char*
-pstrdup (const char *s)
-{
- int len = strlen (s) + 1;
- char *p = (char *) g_malloc (len);
- memcpy (p, s, len);
- return p;
-}
-
-static void *
-alloc_buffer (int size)
-{
- return mono_valloc (NULL, size, MONO_MMAP_READ | MONO_MMAP_WRITE | MONO_MMAP_ANON | MONO_MMAP_PRIVATE, MONO_MEM_ACCOUNT_PROFILER);
-}
-
-static void
-free_buffer (void *buf, int size)
-{
- mono_vfree (buf, size, MONO_MEM_ACCOUNT_PROFILER);
-}
-
-static LogBuffer*
-create_buffer (uintptr_t tid)
-{
- LogBuffer* buf = (LogBuffer *) alloc_buffer (BUFFER_SIZE);
-
- InterlockedIncrement (&buffer_allocations_ctr);
-
- buf->size = BUFFER_SIZE;
- buf->time_base = current_time ();
- buf->last_time = buf->time_base;
- buf->buf_end = (unsigned char *) buf + buf->size;
- buf->cursor = buf->buf;
- buf->thread_id = tid;
-
- return buf;
-}
-
-/*
- * Must be called with the reader lock held if thread is the current thread, or
- * the exclusive lock if thread is a different thread. However, if thread is
- * the current thread, and init_thread () was called with add_to_lls = FALSE,
- * then no locking is necessary.
- */
-static void
-init_buffer_state (MonoProfilerThread *thread)
-{
- thread->buffer = create_buffer (thread->node.key);
- thread->methods = NULL;
-}
-
-static void
-clear_hazard_pointers (MonoThreadHazardPointers *hp)
-{
- mono_hazard_pointer_clear (hp, 0);
- mono_hazard_pointer_clear (hp, 1);
- mono_hazard_pointer_clear (hp, 2);
-}
-
-static MonoProfilerThread *
-init_thread (MonoProfiler *prof, gboolean add_to_lls)
-{
- MonoProfilerThread *thread = PROF_TLS_GET ();
-
- /*
- * Sometimes we may try to initialize a thread twice. One example is the
- * main thread: We initialize it when setting up the profiler, but we will
- * also get a thread_start () callback for it. Another example is when
- * attaching new threads to the runtime: We may get a gc_alloc () callback
- * for that thread's thread object (where we initialize it), soon followed
- * by a thread_start () callback.
- *
- * These cases are harmless anyhow. Just return if we've already done the
- * initialization work.
- */
- if (thread)
- return thread;
-
- thread = g_malloc (sizeof (MonoProfilerThread));
- thread->node.key = thread_id ();
- thread->profiler = prof;
- thread->attached = add_to_lls;
- thread->call_depth = 0;
- thread->busy = 0;
- thread->ended = FALSE;
-
- init_buffer_state (thread);
-
- /*
- * Some internal profiler threads don't need to be cleaned up
- * by the main thread on shutdown.
- */
- if (add_to_lls) {
- MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
- g_assert (mono_lls_insert (&profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
- clear_hazard_pointers (hp);
- }
-
- PROF_TLS_SET (thread);
-
- return thread;
-}
-
-// Only valid if init_thread () was called with add_to_lls = FALSE.
-static void
-deinit_thread (MonoProfilerThread *thread)
-{
- g_assert (!thread->attached && "Why are we manually freeing an attached thread?");
-
- g_free (thread);
- PROF_TLS_SET (NULL);
-}
-
-// Only valid if init_thread () was called with add_to_lls = FALSE.
-static LogBuffer *
-ensure_logbuf_unsafe (MonoProfilerThread *thread, int bytes)
-{
- LogBuffer *old = thread->buffer;
-
- if (old && old->cursor + bytes + 100 < old->buf_end)
- return old;
-
- LogBuffer *new_ = create_buffer (thread->node.key);
- new_->next = old;
- thread->buffer = new_;
-
- return new_;
-}
-
-static void
-encode_uleb128 (uint64_t value, uint8_t *buf, uint8_t **endbuf)
-{
- uint8_t *p = buf;
-
- do {
- uint8_t b = value & 0x7f;
- value >>= 7;
-
- if (value != 0) /* more bytes to come */
- b |= 0x80;
-
- *p ++ = b;
- } while (value);
-
- *endbuf = p;
-}
-
-static void
-encode_sleb128 (intptr_t value, uint8_t *buf, uint8_t **endbuf)
-{
- int more = 1;
- int negative = (value < 0);
- unsigned int size = sizeof (intptr_t) * 8;
- uint8_t byte;
- uint8_t *p = buf;
-
- while (more) {
- byte = value & 0x7f;
- value >>= 7;
-
- /* the following is unnecessary if the
- * implementation of >>= uses an arithmetic rather
- * than logical shift for a signed left operand
- */
- if (negative)
- /* sign extend */
- value |= - ((intptr_t) 1 <<(size - 7));
-
- /* sign bit of byte is second high order bit (0x40) */
- if ((value == 0 && !(byte & 0x40)) ||
- (value == -1 && (byte & 0x40)))
- more = 0;
- else
- byte |= 0x80;
-
- *p ++= byte;
- }
-
- *endbuf = p;
-}
-
-static void
-emit_byte (LogBuffer *logbuffer, int value)
-{
- logbuffer->cursor [0] = value;
- logbuffer->cursor++;
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_value (LogBuffer *logbuffer, int value)
-{
- encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_time (LogBuffer *logbuffer, uint64_t value)
-{
- uint64_t tdiff = value - logbuffer->last_time;
- encode_uleb128 (tdiff, logbuffer->cursor, &logbuffer->cursor);
- logbuffer->last_time = value;
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_event_time (LogBuffer *logbuffer, int event, uint64_t time)
-{
- emit_byte (logbuffer, event);
- emit_time (logbuffer, time);
-}
-
-static void
-emit_event (LogBuffer *logbuffer, int event)
-{
- emit_event_time (logbuffer, event, current_time ());
-}
-
-static void
-emit_svalue (LogBuffer *logbuffer, int64_t value)
-{
- encode_sleb128 (value, logbuffer->cursor, &logbuffer->cursor);
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_uvalue (LogBuffer *logbuffer, uint64_t value)
-{
- encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_ptr (LogBuffer *logbuffer, void *ptr)
-{
- if (!logbuffer->ptr_base)
- logbuffer->ptr_base = (uintptr_t) ptr;
-
- emit_svalue (logbuffer, (intptr_t) ptr - logbuffer->ptr_base);
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_method_inner (LogBuffer *logbuffer, void *method)
-{
- if (!logbuffer->method_base) {
- logbuffer->method_base = (intptr_t) method;
- logbuffer->last_method = (intptr_t) method;
- }
-
- encode_sleb128 ((intptr_t) ((char *) method - (char *) logbuffer->last_method), logbuffer->cursor, &logbuffer->cursor);
- logbuffer->last_method = (intptr_t) method;
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-register_method_local (MonoMethod *method, MonoJitInfo *ji)
-{
- MonoProfilerThread *thread = PROF_TLS_GET ();
-
- if (!mono_conc_hashtable_lookup (thread->profiler->method_table, method)) {
- MethodInfo *info = (MethodInfo *) g_malloc (sizeof (MethodInfo));
-
- info->method = method;
- info->ji = ji;
- info->time = current_time ();
-
- GPtrArray *arr = thread->methods ? thread->methods : (thread->methods = g_ptr_array_new ());
- g_ptr_array_add (arr, info);
- }
-}
-
-static void
-emit_method (LogBuffer *logbuffer, MonoMethod *method)
-{
- register_method_local (method, NULL);
- emit_method_inner (logbuffer, method);
-}
-
-static void
-emit_obj (LogBuffer *logbuffer, void *ptr)
-{
- if (!logbuffer->obj_base)
- logbuffer->obj_base = (uintptr_t) ptr >> 3;
-
- emit_svalue (logbuffer, ((uintptr_t) ptr >> 3) - logbuffer->obj_base);
-
- g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
-}
-
-static void
-emit_string (LogBuffer *logbuffer, const char *str, size_t size)
-{
- size_t i = 0;
- if (str) {
- for (; i < size; i++) {
- if (str[i] == '\0')
- break;
- emit_byte (logbuffer, str [i]);
- }
- }
- emit_byte (logbuffer, '\0');
-}
-
-static void
-emit_double (LogBuffer *logbuffer, double value)
-{
- int i;
- unsigned char buffer[8];
- memcpy (buffer, &value, 8);
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- for (i = 7; i >= 0; i--)
-#else
- for (i = 0; i < 8; i++)
-#endif
- emit_byte (logbuffer, buffer[i]);
-}
-
-static char*
-write_int16 (char *buf, int32_t value)
-{
- int i;
- for (i = 0; i < 2; ++i) {
- buf [i] = value;
- value >>= 8;
- }
- return buf + 2;
-}
-
-static char*
-write_int32 (char *buf, int32_t value)
-{
- int i;
- for (i = 0; i < 4; ++i) {
- buf [i] = value;
- value >>= 8;
- }
- return buf + 4;
-}
-
-static char*
-write_int64 (char *buf, int64_t value)
-{
- int i;
- for (i = 0; i < 8; ++i) {
- buf [i] = value;
- value >>= 8;
- }
- return buf + 8;
-}
-
-static char *
-write_header_string (char *p, const char *str)
-{
- size_t len = strlen (str) + 1;
-
- p = write_int32 (p, len);
- strcpy (p, str);
-
- return p + len;
-}
-
-static void
-dump_header (MonoProfiler *profiler)
-{
- const char *args = profiler->args;
- const char *arch = mono_config_get_cpu ();
- const char *os = mono_config_get_os ();
-
- char *hbuf = g_malloc (
- sizeof (gint32) /* header id */ +
- sizeof (gint8) /* major version */ +
- sizeof (gint8) /* minor version */ +
- sizeof (gint8) /* data version */ +
- sizeof (gint8) /* word size */ +
- sizeof (gint64) /* startup time */ +
- sizeof (gint32) /* timer overhead */ +
- sizeof (gint32) /* flags */ +
- sizeof (gint32) /* process id */ +
- sizeof (gint16) /* command port */ +
- sizeof (gint32) + strlen (args) + 1 /* arguments */ +
- sizeof (gint32) + strlen (arch) + 1 /* architecture */ +
- sizeof (gint32) + strlen (os) + 1 /* operating system */
- );
- char *p = hbuf;
-
- p = write_int32 (p, LOG_HEADER_ID);
- *p++ = LOG_VERSION_MAJOR;
- *p++ = LOG_VERSION_MINOR;
- *p++ = LOG_DATA_VERSION;
- *p++ = sizeof (void *);
- p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
- p = write_int32 (p, timer_overhead);
- p = write_int32 (p, 0); /* flags */
- p = write_int32 (p, process_id ());
- p = write_int16 (p, profiler->command_port);
- p = write_header_string (p, args);
- p = write_header_string (p, arch);
- p = write_header_string (p, os);
-
-#if defined (HAVE_SYS_ZLIB)
- if (profiler->gzfile) {
- gzwrite (profiler->gzfile, hbuf, p - hbuf);
- } else
-#endif
- {
- fwrite (hbuf, p - hbuf, 1, profiler->file);
- fflush (profiler->file);
- }
-
- g_free (hbuf);
-}
-
-/*
- * Must be called with the reader lock held if thread is the current thread, or
- * the exclusive lock if thread is a different thread. However, if thread is
- * the current thread, and init_thread () was called with add_to_lls = FALSE,
- * then no locking is necessary.
- */
-static void
-send_buffer (MonoProfilerThread *thread)
-{
- WriterQueueEntry *entry = mono_lock_free_alloc (&thread->profiler->writer_entry_allocator);
- entry->methods = thread->methods;
- entry->buffer = thread->buffer;
-
- mono_lock_free_queue_node_init (&entry->node, FALSE);
-
- mono_lock_free_queue_enqueue (&thread->profiler->writer_queue, &entry->node);
- mono_os_sem_post (&thread->profiler->writer_queue_sem);
-}
-
-static void
-free_thread (gpointer p)
-{
- MonoProfilerThread *thread = p;
-
- if (!thread->ended) {
- /*
- * The thread is being cleaned up by the main thread during
- * shutdown. This typically happens for internal runtime
- * threads. We need to synthesize a thread end event.
- */
-
- InterlockedIncrement (&thread_ends_ctr);
-
- LogBuffer *buf = ensure_logbuf_unsafe (thread,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* tid */
- );
-
- emit_event (buf, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (buf, TYPE_THREAD);
- emit_ptr (buf, (void *) thread->node.key);
- }
-
- send_buffer (thread);
-
- g_free (thread);
-}
-
-static void
-remove_thread (MonoProfilerThread *thread)
-{
- MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
-
- if (mono_lls_remove (&profiler_thread_list, hp, &thread->node))
- mono_thread_hazardous_try_free (thread, free_thread);
-
- clear_hazard_pointers (hp);
-}
-
-static void
-dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
-{
- char hbuf [128];
- char *p = hbuf;
-
- if (buf->next)
- dump_buffer (profiler, buf->next);
-
- if (buf->cursor - buf->buf) {
- p = write_int32 (p, BUF_ID);
- p = write_int32 (p, buf->cursor - buf->buf);
- p = write_int64 (p, buf->time_base);
- p = write_int64 (p, buf->ptr_base);
- p = write_int64 (p, buf->obj_base);
- p = write_int64 (p, buf->thread_id);
- p = write_int64 (p, buf->method_base);
-
-#if defined (HAVE_SYS_ZLIB)
- if (profiler->gzfile) {
- gzwrite (profiler->gzfile, hbuf, p - hbuf);
- gzwrite (profiler->gzfile, buf->buf, buf->cursor - buf->buf);
- } else
-#endif
- {
- fwrite (hbuf, p - hbuf, 1, profiler->file);
- fwrite (buf->buf, buf->cursor - buf->buf, 1, profiler->file);
- fflush (profiler->file);
- }
- }
-
- free_buffer (buf, buf->size);
-}
-
-static void
-dump_buffer_threadless (MonoProfiler *profiler, LogBuffer *buf)
-{
- for (LogBuffer *iter = buf; iter; iter = iter->next)
- iter->thread_id = 0;
-
- dump_buffer (profiler, buf);
-}
-
-static void
-process_requests (void)
-{
- if (heapshot_requested)
- mono_gc_collect (mono_gc_max_generation ());
-}
-
-// Only valid if init_thread () was called with add_to_lls = FALSE.
-static void
-send_log_unsafe (gboolean if_needed)
-{
- MonoProfilerThread *thread = PROF_TLS_GET ();
-
- if (!if_needed || (if_needed && thread->buffer->next)) {
- if (!thread->attached)
- for (LogBuffer *iter = thread->buffer; iter; iter = iter->next)
- iter->thread_id = 0;
-
- send_buffer (thread);
- init_buffer_state (thread);
- }
-}
-
-// Assumes that the exclusive lock is held.
-static void
-sync_point_flush (void)
-{
- g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
-
- MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
- g_assert (thread->attached && "Why is a thread in the LLS not attached?");
-
- send_buffer (thread);
- init_buffer_state (thread);
- } MONO_LLS_FOREACH_SAFE_END
-}
-
-// Assumes that the exclusive lock is held.
-static void
-sync_point_mark (MonoProfilerSyncPointType type)
-{
- g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
-
- ENTER_LOG (&sync_points_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* type */
- );
-
- emit_event (logbuffer, TYPE_META | TYPE_SYNC_POINT);
- emit_byte (logbuffer, type);
-
- EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
-
- send_log_unsafe (FALSE);
-}
-
-// Assumes that the exclusive lock is held.
-static void
-sync_point (MonoProfilerSyncPointType type)
-{
- sync_point_flush ();
- sync_point_mark (type);
-}
-
-static int
-gc_reference (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num, MonoObject **refs, uintptr_t *offsets, void *data)
-{
- /* account for object alignment in the heap */
- size += 7;
- size &= ~7;
-
- ENTER_LOG (&heap_objects_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* obj */ +
- LEB128_SIZE /* klass */ +
- LEB128_SIZE /* size */ +
- LEB128_SIZE /* num */ +
- num * (
- LEB128_SIZE /* offset */ +
- LEB128_SIZE /* ref */
- )
- );
-
- emit_event (logbuffer, TYPE_HEAP_OBJECT | TYPE_HEAP);
- emit_obj (logbuffer, obj);
- emit_ptr (logbuffer, klass);
- emit_value (logbuffer, size);
- emit_value (logbuffer, num);
-
- uintptr_t last_offset = 0;
-
- for (int i = 0; i < num; ++i) {
- emit_value (logbuffer, offsets [i] - last_offset);
- last_offset = offsets [i];
- emit_obj (logbuffer, refs [i]);
- }
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- return 0;
-}
-
-static unsigned int hs_mode_ms = 0;
-static unsigned int hs_mode_gc = 0;
-static unsigned int hs_mode_ondemand = 0;
-static unsigned int gc_count = 0;
-static uint64_t last_hs_time = 0;
-static gboolean do_heap_walk = FALSE;
-
-static void
-heap_walk (MonoProfiler *profiler)
-{
- ENTER_LOG (&heap_starts_ctr, logbuffer,
- EVENT_SIZE /* event */
- );
-
- emit_event (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- mono_gc_walk_heap (0, gc_reference, NULL);
-
- ENTER_LOG (&heap_ends_ctr, logbuffer,
- EVENT_SIZE /* event */
- );
-
- emit_event (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-static void
-gc_roots (MonoProfiler *prof, int num, void **objects, int *root_types, uintptr_t *extra_info)
-{
- ENTER_LOG (&heap_roots_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* num */ +
- LEB128_SIZE /* collections */ +
- num * (
- LEB128_SIZE /* object */ +
- LEB128_SIZE /* root type */ +
- LEB128_SIZE /* extra info */
- )
- );
-
- emit_event (logbuffer, TYPE_HEAP_ROOT | TYPE_HEAP);
- emit_value (logbuffer, num);
- emit_value (logbuffer, mono_gc_collection_count (mono_gc_max_generation ()));
-
- for (int i = 0; i < num; ++i) {
- emit_obj (logbuffer, objects [i]);
- emit_byte (logbuffer, root_types [i]);
- emit_value (logbuffer, extra_info [i]);
- }
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-static void
-gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
-{
- ENTER_LOG (&gc_events_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* gc event */ +
- BYTE_SIZE /* generation */
- );
-
- emit_event (logbuffer, TYPE_GC_EVENT | TYPE_GC);
- emit_byte (logbuffer, ev);
- emit_byte (logbuffer, generation);
-
- EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
-
- switch (ev) {
- case MONO_GC_EVENT_START:
- if (generation == mono_gc_max_generation ())
- gc_count++;
-
- uint64_t now = current_time ();
-
- if (hs_mode_ms && (now - last_hs_time) / 1000 * 1000 >= hs_mode_ms)
- do_heap_walk = TRUE;
- else if (hs_mode_gc && !(gc_count % hs_mode_gc))
- do_heap_walk = TRUE;
- else if (hs_mode_ondemand)
- do_heap_walk = heapshot_requested;
- else if (!hs_mode_ms && !hs_mode_gc && generation == mono_gc_max_generation ())
- do_heap_walk = TRUE;
- break;
- case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
- /*
- * Ensure that no thread can be in the middle of writing to
- * a buffer when the world stops...
- */
- buffer_lock_excl ();
- break;
- case MONO_GC_EVENT_POST_STOP_WORLD:
- /*
- * ... So that we now have a consistent view of all buffers.
- * This allows us to flush them. We need to do this because
- * they may contain object allocation events that need to be
- * committed to the log file before any object move events
- * that will be produced during this GC.
- */
- sync_point (SYNC_POINT_WORLD_STOP);
- break;
- case MONO_GC_EVENT_PRE_START_WORLD:
- if (do_heap_shot && do_heap_walk) {
- heap_walk (profiler);
-
- do_heap_walk = FALSE;
- heapshot_requested = 0;
- last_hs_time = current_time ();
- }
- break;
- case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
- /*
- * Similarly, we must now make sure that any object moves
- * written to the GC thread's buffer are flushed. Otherwise,
- * object allocation events for certain addresses could come
- * after the move events that made those addresses available.
- */
- sync_point_mark (SYNC_POINT_WORLD_START);
-
- /*
- * Finally, it is safe to allow other threads to write to
- * their buffers again.
- */
- buffer_unlock_excl ();
- break;
- default:
- break;
- }
-}
-
-static void
-gc_resize (MonoProfiler *profiler, int64_t new_size)
-{
- ENTER_LOG (&gc_resizes_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* new size */
- );
-
- emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
- emit_value (logbuffer, new_size);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-// If you alter MAX_FRAMES, you may need to alter SAMPLE_BLOCK_SIZE too.
-#define MAX_FRAMES 32
-
-typedef struct {
- int count;
- MonoMethod* methods [MAX_FRAMES];
- int32_t il_offsets [MAX_FRAMES];
- int32_t native_offsets [MAX_FRAMES];
-} FrameData;
-
-static int num_frames = MAX_FRAMES;
-
-static mono_bool
-walk_stack (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
-{
- FrameData *frame = (FrameData *)data;
- if (method && frame->count < num_frames) {
- frame->il_offsets [frame->count] = il_offset;
- frame->native_offsets [frame->count] = native_offset;
- frame->methods [frame->count++] = method;
- //printf ("In %d %s at %d (native: %d)\n", frame->count, mono_method_get_name (method), il_offset, native_offset);
- }
- return frame->count == num_frames;
-}
-
-/*
- * a note about stack walks: they can cause more profiler events to fire,
- * so we need to make sure they don't happen after we started emitting an
- * event, hence the collect_bt/emit_bt split.
- */
-static void
-collect_bt (FrameData *data)
-{
- data->count = 0;
- mono_stack_walk_no_il (walk_stack, data);
-}
-
-static void
-emit_bt (MonoProfiler *prof, LogBuffer *logbuffer, FrameData *data)
-{
- /* FIXME: this is actually tons of data and we should
- * just output it the first time and use an id the next
- */
- if (data->count > num_frames)
- printf ("bad num frames: %d\n", data->count);
- emit_value (logbuffer, data->count);
- //if (*p != data.count) {
- // printf ("bad num frames enc at %d: %d -> %d\n", count, data.count, *p); printf ("frames end: %p->%p\n", p, logbuffer->cursor); exit(0);}
- while (data->count) {
- emit_method (logbuffer, data->methods [--data->count]);
- }
-}
-
-static void
-gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
-{
- init_thread (prof, TRUE);
-
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_ALLOC_BT : 0;
- FrameData data;
- uintptr_t len = mono_object_get_size (obj);
- /* account for object alignment in the heap */
- len += 7;
- len &= ~7;
-
- if (do_bt)
- collect_bt (&data);
-
- ENTER_LOG (&gc_allocs_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* klass */ +
- LEB128_SIZE /* obj */ +
- LEB128_SIZE /* size */ +
- (do_bt ? (
- LEB128_SIZE /* count */ +
- data.count * (
- LEB128_SIZE /* method */
- )
- ) : 0)
- );
-
- emit_event (logbuffer, do_bt | TYPE_ALLOC);
- emit_ptr (logbuffer, klass);
- emit_obj (logbuffer, obj);
- emit_value (logbuffer, len);
-
- if (do_bt)
- emit_bt (prof, logbuffer, &data);
-
- EXIT_LOG;
-}
-
-static void
-gc_moves (MonoProfiler *prof, void **objects, int num)
-{
- ENTER_LOG (&gc_moves_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* num */ +
- num * (
- LEB128_SIZE /* object */
- )
- );
-
- emit_event (logbuffer, TYPE_GC_MOVE | TYPE_GC);
- emit_value (logbuffer, num);
-
- for (int i = 0; i < num; ++i)
- emit_obj (logbuffer, objects [i]);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-static void
-gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj)
-{
- int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
- FrameData data;
-
- if (do_bt)
- collect_bt (&data);
-
- gint32 *ctr = op == MONO_PROFILER_GC_HANDLE_CREATED ? &gc_handle_creations_ctr : &gc_handle_deletions_ctr;
-
- ENTER_LOG (ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* type */ +
- LEB128_SIZE /* handle */ +
- (op == MONO_PROFILER_GC_HANDLE_CREATED ? (
- LEB128_SIZE /* obj */
- ) : 0) +
- (do_bt ? (
- LEB128_SIZE /* count */ +
- data.count * (
- LEB128_SIZE /* method */
- )
- ) : 0)
- );
-
- if (op == MONO_PROFILER_GC_HANDLE_CREATED)
- emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
- else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
- emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
- else
- g_assert_not_reached ();
-
- emit_value (logbuffer, type);
- emit_value (logbuffer, handle);
-
- if (op == MONO_PROFILER_GC_HANDLE_CREATED)
- emit_obj (logbuffer, obj);
-
- if (do_bt)
- emit_bt (prof, logbuffer, &data);
-
- EXIT_LOG;
-}
-
-static void
-finalize_begin (MonoProfiler *prof)
-{
- ENTER_LOG (&finalize_begins_ctr, buf,
- EVENT_SIZE /* event */
- );
-
- emit_event (buf, TYPE_GC_FINALIZE_START | TYPE_GC);
-
- EXIT_LOG;
-}
-
-static void
-finalize_end (MonoProfiler *prof)
-{
- ENTER_LOG (&finalize_ends_ctr, buf,
- EVENT_SIZE /* event */
- );
-
- emit_event (buf, TYPE_GC_FINALIZE_END | TYPE_GC);
-
- EXIT_LOG;
-}
-
-static void
-finalize_object_begin (MonoProfiler *prof, MonoObject *obj)
-{
- ENTER_LOG (&finalize_object_begins_ctr, buf,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* obj */
- );
-
- emit_event (buf, TYPE_GC_FINALIZE_OBJECT_START | TYPE_GC);
- emit_obj (buf, obj);
-
- EXIT_LOG;
-}
-
-static void
-finalize_object_end (MonoProfiler *prof, MonoObject *obj)
-{
- ENTER_LOG (&finalize_object_ends_ctr, buf,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* obj */
- );
-
- emit_event (buf, TYPE_GC_FINALIZE_OBJECT_END | TYPE_GC);
- emit_obj (buf, obj);
-
- EXIT_LOG;
-}
-
-static char*
-push_nesting (char *p, MonoClass *klass)
-{
- MonoClass *nesting;
- const char *name;
- const char *nspace;
- nesting = mono_class_get_nesting_type (klass);
- if (nesting) {
- p = push_nesting (p, nesting);
- *p++ = '/';
- *p = 0;
- }
- name = mono_class_get_name (klass);
- nspace = mono_class_get_namespace (klass);
- if (*nspace) {
- strcpy (p, nspace);
- p += strlen (nspace);
- *p++ = '.';
- *p = 0;
- }
- strcpy (p, name);
- p += strlen (name);
- return p;
-}
-
-static char*
-type_name (MonoClass *klass)
-{
- char buf [1024];
- char *p;
- push_nesting (buf, klass);
- p = (char *) g_malloc (strlen (buf) + 1);
- strcpy (p, buf);
- return p;
-}
-
-static void
-image_loaded (MonoProfiler *prof, MonoImage *image, int result)
-{
- if (result != MONO_PROFILE_OK)
- return;
-
- const char *name = mono_image_get_filename (image);
- int nlen = strlen (name) + 1;
-
- ENTER_LOG (&image_loads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* image */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_IMAGE);
- emit_ptr (logbuffer, image);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-}
-
-static void
-image_unloaded (MonoProfiler *prof, MonoImage *image)
-{
- const char *name = mono_image_get_filename (image);
- int nlen = strlen (name) + 1;
-
- ENTER_LOG (&image_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* image */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_IMAGE);
- emit_ptr (logbuffer, image);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-}
-
-static void
-assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly, int result)
-{
- if (result != MONO_PROFILE_OK)
- return;
-
- char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
- int nlen = strlen (name) + 1;
-
- ENTER_LOG (&assembly_loads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* assembly */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_ASSEMBLY);
- emit_ptr (logbuffer, assembly);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-
- mono_free (name);
-}
-
-static void
-assembly_unloaded (MonoProfiler *prof, MonoAssembly *assembly)
-{
- char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
- int nlen = strlen (name) + 1;
-
- ENTER_LOG (&assembly_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* assembly */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_ASSEMBLY);
- emit_ptr (logbuffer, assembly);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-
- mono_free (name);
-}
-
-static void
-class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
-{
- if (result != MONO_PROFILE_OK)
- return;
-
- char *name;
-
- if (InterlockedRead (&runtime_inited))
- name = mono_type_get_name (mono_class_get_type (klass));
- else
- name = type_name (klass);
-
- int nlen = strlen (name) + 1;
- MonoImage *image = mono_class_get_image (klass);
-
- ENTER_LOG (&class_loads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* klass */ +
- LEB128_SIZE /* image */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_CLASS);
- emit_ptr (logbuffer, klass);
- emit_ptr (logbuffer, image);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-
- if (runtime_inited)
- mono_free (name);
- else
- g_free (name);
-}
-
-static void
-class_unloaded (MonoProfiler *prof, MonoClass *klass)
-{
- char *name;
-
- if (InterlockedRead (&runtime_inited))
- name = mono_type_get_name (mono_class_get_type (klass));
- else
- name = type_name (klass);
-
- int nlen = strlen (name) + 1;
- MonoImage *image = mono_class_get_image (klass);
-
- ENTER_LOG (&class_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* klass */ +
- LEB128_SIZE /* image */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_CLASS);
- emit_ptr (logbuffer, klass);
- emit_ptr (logbuffer, image);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-
- if (runtime_inited)
- mono_free (name);
- else
- g_free (name);
-}
-
-static void process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method);
-
-static void
-method_enter (MonoProfiler *prof, MonoMethod *method)
-{
- process_method_enter_coverage (prof, method);
-
- if (!only_coverage && PROF_TLS_GET ()->call_depth++ <= max_call_depth) {
- ENTER_LOG (&method_entries_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* method */
- );
-
- emit_event (logbuffer, TYPE_ENTER | TYPE_METHOD);
- emit_method (logbuffer, method);
-
- EXIT_LOG;
- }
-}
-
-static void
-method_leave (MonoProfiler *prof, MonoMethod *method)
-{
- if (!only_coverage && --PROF_TLS_GET ()->call_depth <= max_call_depth) {
- ENTER_LOG (&method_exits_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* method */
- );
-
- emit_event (logbuffer, TYPE_LEAVE | TYPE_METHOD);
- emit_method (logbuffer, method);
-
- EXIT_LOG;
- }
-}
-
-static void
-method_exc_leave (MonoProfiler *prof, MonoMethod *method)
-{
- if (!only_coverage && !nocalls && --PROF_TLS_GET ()->call_depth <= max_call_depth) {
- ENTER_LOG (&method_exception_exits_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* method */
- );
-
- emit_event (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
- emit_method (logbuffer, method);
-
- EXIT_LOG;
- }
-}
-
-static void
-method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji, int result)
-{
- if (result != MONO_PROFILE_OK)
- return;
-
- register_method_local (method, ji);
-
- process_requests ();
-}
-
-static void
-code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
-{
- char *name;
- int nlen;
-
- if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
- name = (char *) data;
- nlen = strlen (name) + 1;
- } else {
- name = NULL;
- nlen = 0;
- }
-
- ENTER_LOG (&code_buffers_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* buffer */ +
- LEB128_SIZE /* size */ +
- (name ? (
- nlen /* name */
- ) : 0)
- );
-
- emit_event (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
- emit_byte (logbuffer, type);
- emit_ptr (logbuffer, buffer);
- emit_value (logbuffer, size);
-
- if (name) {
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
- }
-
- EXIT_LOG;
-}
-
-static void
-throw_exc (MonoProfiler *prof, MonoObject *object)
-{
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_THROW_BT : 0;
- FrameData data;
-
- if (do_bt)
- collect_bt (&data);
-
- ENTER_LOG (&exception_throws_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* object */ +
- (do_bt ? (
- LEB128_SIZE /* count */ +
- data.count * (
- LEB128_SIZE /* method */
- )
- ) : 0)
- );
-
- emit_event (logbuffer, do_bt | TYPE_EXCEPTION);
- emit_obj (logbuffer, object);
-
- if (do_bt)
- emit_bt (prof, logbuffer, &data);
-
- EXIT_LOG;
-}
-
-static void
-clause_exc (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num)
-{
- ENTER_LOG (&exception_clauses_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* clause type */ +
- LEB128_SIZE /* clause num */ +
- LEB128_SIZE /* method */
- );
-
- emit_event (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
- emit_byte (logbuffer, clause_type);
- emit_value (logbuffer, clause_num);
- emit_method (logbuffer, method);
-
- EXIT_LOG;
-}
-
-static void
-monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent event)
-{
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces && event == MONO_PROFILER_MONITOR_CONTENTION) ? TYPE_MONITOR_BT : 0;
- FrameData data;
-
- if (do_bt)
- collect_bt (&data);
-
- gint32 *ctr;
-
- switch (event) {
- case MONO_PROFILER_MONITOR_CONTENTION:
- ctr = &monitor_contentions_ctr;
- break;
- case MONO_PROFILER_MONITOR_DONE:
- ctr = &monitor_acquisitions_ctr;
- break;
- case MONO_PROFILER_MONITOR_FAIL:
- ctr = &monitor_failures_ctr;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- ENTER_LOG (ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* object */ +
- (do_bt ? (
- LEB128_SIZE /* count */ +
- data.count * (
- LEB128_SIZE /* method */
- )
- ) : 0)
- );
-
- emit_event (logbuffer, (event << 4) | do_bt | TYPE_MONITOR);
- emit_obj (logbuffer, object);
-
- if (do_bt)
- emit_bt (profiler, logbuffer, &data);
-
- EXIT_LOG;
-}
-
-static void
-thread_start (MonoProfiler *prof, uintptr_t tid)
-{
- init_thread (prof, TRUE);
-
- ENTER_LOG (&thread_starts_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* tid */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_THREAD);
- emit_ptr (logbuffer, (void*) tid);
-
- EXIT_LOG;
-}
-
-static void
-thread_end (MonoProfiler *prof, uintptr_t tid)
-{
- ENTER_LOG (&thread_ends_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* tid */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_THREAD);
- emit_ptr (logbuffer, (void*) tid);
-
- EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
-
- MonoProfilerThread *thread = PROF_TLS_GET ();
-
- thread->ended = TRUE;
- remove_thread (thread);
-
- PROF_TLS_SET (NULL);
-}
-
-static void
-thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
-{
- int len = strlen (name) + 1;
-
- ENTER_LOG (&thread_names_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* tid */ +
- len /* name */
- );
-
- emit_event (logbuffer, TYPE_METADATA);
- emit_byte (logbuffer, TYPE_THREAD);
- emit_ptr (logbuffer, (void*)tid);
- memcpy (logbuffer->cursor, name, len);
- logbuffer->cursor += len;
-
- EXIT_LOG;
-}
-
-static void
-domain_loaded (MonoProfiler *prof, MonoDomain *domain, int result)
-{
- if (result != MONO_PROFILE_OK)
- return;
-
- ENTER_LOG (&domain_loads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* domain id */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_DOMAIN);
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
-
- EXIT_LOG;
-}
-
-static void
-domain_unloaded (MonoProfiler *prof, MonoDomain *domain)
-{
- ENTER_LOG (&domain_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* domain id */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_DOMAIN);
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
-
- EXIT_LOG;
-}
-
-static void
-domain_name (MonoProfiler *prof, MonoDomain *domain, const char *name)
-{
- int nlen = strlen (name) + 1;
-
- ENTER_LOG (&domain_names_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* domain id */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_METADATA);
- emit_byte (logbuffer, TYPE_DOMAIN);
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-}
-
-static void
-context_loaded (MonoProfiler *prof, MonoAppContext *context)
-{
- ENTER_LOG (&context_loads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* context id */ +
- LEB128_SIZE /* domain id */
- );
-
- emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_CONTEXT);
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
-
- EXIT_LOG;
-}
-
-static void
-context_unloaded (MonoProfiler *prof, MonoAppContext *context)
-{
- ENTER_LOG (&context_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* context id */ +
- LEB128_SIZE /* domain id */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_CONTEXT);
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
- emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
-
- EXIT_LOG;
-}
-
-typedef struct {
- MonoMethod *method;
- MonoDomain *domain;
- void *base_address;
- int offset;
-} AsyncFrameInfo;
-
-typedef struct {
- MonoLockFreeQueueNode node;
- MonoProfiler *prof;
- uint64_t time;
- uintptr_t tid;
- void *ip;
- int count;
- AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
-} SampleHit;
-
-static mono_bool
-async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void *data)
-{
- SampleHit *sample = (SampleHit *) data;
-
- if (sample->count < num_frames) {
- int i = sample->count;
-
- sample->frames [i].method = method;
- sample->frames [i].domain = domain;
- sample->frames [i].base_address = base_address;
- sample->frames [i].offset = offset;
-
- sample->count++;
- }
-
- return sample->count == num_frames;
-}
-
-#define SAMPLE_SLOT_SIZE(FRAMES) (sizeof (SampleHit) + sizeof (AsyncFrameInfo) * (FRAMES - MONO_ZERO_LEN_ARRAY))
-#define SAMPLE_BLOCK_SIZE (mono_pagesize ())
-
-static void
-enqueue_sample_hit (gpointer p)
-{
- SampleHit *sample = p;
-
- mono_lock_free_queue_node_unpoison (&sample->node);
- mono_lock_free_queue_enqueue (&sample->prof->dumper_queue, &sample->node);
- mono_os_sem_post (&sample->prof->dumper_queue_sem);
-}
-
-static void
-mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
-{
- /*
- * Please note: We rely on the runtime loading the profiler with
- * MONO_DL_EAGER (RTLD_NOW) so that references to runtime functions within
- * this function (and its siblings) are resolved when the profiler is
- * loaded. Otherwise, we would potentially invoke the dynamic linker when
- * invoking runtime functions, which is not async-signal-safe.
- */
-
- if (InterlockedRead (&in_shutdown))
- return;
-
- SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
-
- if (!sample) {
- /*
- * If we're out of reusable sample events and we're not allowed to
- * allocate more, we have no choice but to drop the event.
- */
- if (InterlockedRead (&sample_allocations_ctr) >= max_allocated_sample_hits)
- return;
-
- sample = mono_lock_free_alloc (&profiler->sample_allocator);
- sample->prof = profiler;
- mono_lock_free_queue_node_init (&sample->node, TRUE);
-
- InterlockedIncrement (&sample_allocations_ctr);
- }
-
- sample->count = 0;
- mono_stack_walk_async_safe (&async_walk_stack, context, sample);
-
- sample->time = current_time ();
- sample->tid = thread_id ();
- sample->ip = ip;
-
- mono_thread_hazardous_try_free (sample, enqueue_sample_hit);
-}
-
-static uintptr_t *code_pages = 0;
-static int num_code_pages = 0;
-static int size_code_pages = 0;
-#define CPAGE_SHIFT (9)
-#define CPAGE_SIZE (1 << CPAGE_SHIFT)
-#define CPAGE_MASK (~(CPAGE_SIZE - 1))
-#define CPAGE_ADDR(p) ((p) & CPAGE_MASK)
-
-static uintptr_t
-add_code_page (uintptr_t *hash, uintptr_t hsize, uintptr_t page)
-{
- uintptr_t i;
- uintptr_t start_pos;
- start_pos = (page >> CPAGE_SHIFT) % hsize;
- i = start_pos;
- do {
- if (hash [i] && CPAGE_ADDR (hash [i]) == CPAGE_ADDR (page)) {
- return 0;
- } else if (!hash [i]) {
- hash [i] = page;
- return 1;
- }
- /* wrap around */
- if (++i == hsize)
- i = 0;
- } while (i != start_pos);
- /* should not happen */
- printf ("failed code page store\n");
- return 0;
-}
-
-static void
-add_code_pointer (uintptr_t ip)
-{
- uintptr_t i;
- if (num_code_pages * 2 >= size_code_pages) {
- uintptr_t *n;
- uintptr_t old_size = size_code_pages;
- size_code_pages *= 2;
- if (size_code_pages == 0)
- size_code_pages = 16;
- n = (uintptr_t *) g_calloc (sizeof (uintptr_t) * size_code_pages, 1);
- for (i = 0; i < old_size; ++i) {
- if (code_pages [i])
- add_code_page (n, size_code_pages, code_pages [i]);
- }
- if (code_pages)
- g_free (code_pages);
- code_pages = n;
- }
- num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
-}
-
-/* ELF code crashes on some systems. */
-//#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
-#if 0
-static void
-dump_ubin (MonoProfiler *prof, const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
-{
- int len = strlen (filename) + 1;
-
- ENTER_LOG (&sample_ubins_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* load address */ +
- LEB128_SIZE /* offset */ +
- LEB128_SIZE /* size */ +
- nlen /* file name */
- );
-
- emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
- emit_svalue (logbuffer, load_addr);
- emit_uvalue (logbuffer, offset);
- emit_uvalue (logbuffer, size);
- memcpy (logbuffer->cursor, filename, len);
- logbuffer->cursor += len;
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-#endif
-
-static void
-dump_usym (MonoProfiler *prof, const char *name, uintptr_t value, uintptr_t size)
-{
- int len = strlen (name) + 1;
-
- ENTER_LOG (&sample_usyms_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* value */ +
- LEB128_SIZE /* size */ +
- len /* name */
- );
-
- emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
- emit_ptr (logbuffer, (void*)value);
- emit_value (logbuffer, size);
- memcpy (logbuffer->cursor, name, len);
- logbuffer->cursor += len;
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-/* ELF code crashes on some systems. */
-//#if defined(ELFMAG0)
-#if 0
-
-#if SIZEOF_VOID_P == 4
-#define ELF_WSIZE 32
-#else
-#define ELF_WSIZE 64
-#endif
-#ifndef ElfW
-#define ElfW(type) _ElfW (Elf, ELF_WSIZE, type)
-#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
-#define _ElfW_1(e,w,t) e##w##t
-#endif
-
-static void
-dump_elf_symbols (MonoProfiler *prof, ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
-{
- int i;
- for (i = 0; i < num_symbols; ++i) {
- const char* sym;
- sym = strtab + symbols [i].st_name;
- if (!symbols [i].st_name || !symbols [i].st_size || (symbols [i].st_info & 0xf) != STT_FUNC)
- continue;
- //printf ("symbol %s at %d\n", sym, symbols [i].st_value);
- dump_usym (sym, (uintptr_t)load_addr + symbols [i].st_value, symbols [i].st_size);
- }
-}
-
-static int
-read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
-{
- int fd, i;
- void *data;
- struct stat statb;
- uint64_t file_size;
- ElfW(Ehdr) *header;
- ElfW(Shdr) *sheader;
- ElfW(Shdr) *shstrtabh;
- ElfW(Shdr) *symtabh = NULL;
- ElfW(Shdr) *strtabh = NULL;
- ElfW(Sym) *symbols = NULL;
- const char *strtab;
- int num_symbols;
-
- fd = open (filename, O_RDONLY);
- if (fd < 0)
- return 0;
- if (fstat (fd, &statb) != 0) {
- close (fd);
- return 0;
- }
- file_size = statb.st_size;
- data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
- close (fd);
- if (data == MAP_FAILED)
- return 0;
- header = data;
- if (header->e_ident [EI_MAG0] != ELFMAG0 ||
- header->e_ident [EI_MAG1] != ELFMAG1 ||
- header->e_ident [EI_MAG2] != ELFMAG2 ||
- header->e_ident [EI_MAG3] != ELFMAG3 ) {
- munmap (data, file_size);
- return 0;
- }
- sheader = (void*)((char*)data + header->e_shoff);
- shstrtabh = (void*)((char*)sheader + (header->e_shentsize * header->e_shstrndx));
- strtab = (const char*)data + shstrtabh->sh_offset;
- for (i = 0; i < header->e_shnum; ++i) {
- //printf ("section header: %d\n", sheader->sh_type);
- if (sheader->sh_type == SHT_SYMTAB) {
- symtabh = sheader;
- strtabh = (void*)((char*)data + header->e_shoff + sheader->sh_link * header->e_shentsize);
- /*printf ("symtab section header: %d, .strstr: %d\n", i, sheader->sh_link);*/
- break;
- }
- sheader = (void*)((char*)sheader + header->e_shentsize);
- }
- if (!symtabh || !strtabh) {
- munmap (data, file_size);
- return 0;
- }
- strtab = (const char*)data + strtabh->sh_offset;
- num_symbols = symtabh->sh_size / symtabh->sh_entsize;
- symbols = (void*)((char*)data + symtabh->sh_offset);
- dump_elf_symbols (symbols, num_symbols, strtab, load_addr);
- munmap (data, file_size);
- return 1;
-}
-#endif
-
-/* ELF code crashes on some systems. */
-//#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
-#if 0
-static int
-elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
-{
- MonoProfiler *prof = data;
- char buf [256];
- const char *filename;
- BinaryObject *obj;
- char *a = (void*)info->dlpi_addr;
- int i, num_sym;
- ElfW(Dyn) *dyn = NULL;
- ElfW(Sym) *symtab = NULL;
- ElfW(Word) *hash_table = NULL;
- ElfW(Ehdr) *header = NULL;
- const char* strtab = NULL;
- for (obj = prof->binary_objects; obj; obj = obj->next) {
- if (obj->addr == a)
- return 0;
- }
- filename = info->dlpi_name;
- if (!filename)
- return 0;
- if (!info->dlpi_addr && !filename [0]) {
- int l = readlink ("/proc/self/exe", buf, sizeof (buf) - 1);
- if (l > 0) {
- buf [l] = 0;
- filename = buf;
- }
- }
- obj = g_calloc (sizeof (BinaryObject), 1);
- obj->addr = (void*)info->dlpi_addr;
- obj->name = pstrdup (filename);
- obj->next = prof->binary_objects;
- prof->binary_objects = obj;
- //printf ("loaded file: %s at %p, segments: %d\n", filename, (void*)info->dlpi_addr, info->dlpi_phnum);
- a = NULL;
- for (i = 0; i < info->dlpi_phnum; ++i) {
- //printf ("segment type %d file offset: %d, size: %d\n", info->dlpi_phdr[i].p_type, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
- if (info->dlpi_phdr[i].p_type == PT_LOAD && !header) {
- header = (ElfW(Ehdr)*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
- if (header->e_ident [EI_MAG0] != ELFMAG0 ||
- header->e_ident [EI_MAG1] != ELFMAG1 ||
- header->e_ident [EI_MAG2] != ELFMAG2 ||
- header->e_ident [EI_MAG3] != ELFMAG3 ) {
- header = NULL;
- }
- dump_ubin (prof, filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
- } else if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
- dyn = (ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
- }
- }
- if (read_elf_symbols (prof, filename, (void*)info->dlpi_addr))
- return 0;
- if (!info->dlpi_name || !info->dlpi_name[0])
- return 0;
- if (!dyn)
- return 0;
- for (i = 0; dyn [i].d_tag != DT_NULL; ++i) {
- if (dyn [i].d_tag == DT_SYMTAB) {
- if (symtab && do_debug)
- printf ("multiple symtabs: %d\n", i);
- symtab = (ElfW(Sym) *)(a + dyn [i].d_un.d_ptr);
- } else if (dyn [i].d_tag == DT_HASH) {
- hash_table = (ElfW(Word) *)(a + dyn [i].d_un.d_ptr);
- } else if (dyn [i].d_tag == DT_STRTAB) {
- strtab = (const char*)(a + dyn [i].d_un.d_ptr);
- }
- }
- if (!hash_table)
- return 0;
- num_sym = hash_table [1];
- dump_elf_symbols (prof, symtab, num_sym, strtab, (void*)info->dlpi_addr);
- return 0;
-}
-
-static int
-load_binaries (MonoProfiler *prof)
-{
- dl_iterate_phdr (elf_dl_callback, prof);
- return 1;
-}
-#else
-static int
-load_binaries (MonoProfiler *prof)
-{
- return 0;
-}
-#endif
-
-static const char*
-symbol_for (uintptr_t code)
-{
-#ifdef HAVE_DLADDR
- void *ip = (void*)code;
- Dl_info di;
- if (dladdr (ip, &di)) {
- if (di.dli_sname)
- return di.dli_sname;
- } else {
- /* char **names;
- names = backtrace_symbols (&ip, 1);
- if (names) {
- const char* p = names [0];
- g_free (names);
- return p;
- }
- */
- }
-#endif
- return NULL;
-}
-
-static void
-dump_unmanaged_coderefs (MonoProfiler *prof)
-{
- int i;
- const char* last_symbol;
- uintptr_t addr, page_end;
-
- if (load_binaries (prof))
- return;
- for (i = 0; i < size_code_pages; ++i) {
- const char* sym;
- if (!code_pages [i] || code_pages [i] & 1)
- continue;
- last_symbol = NULL;
- addr = CPAGE_ADDR (code_pages [i]);
- page_end = addr + CPAGE_SIZE;
- code_pages [i] |= 1;
- /* we dump the symbols for the whole page */
- for (; addr < page_end; addr += 16) {
- sym = symbol_for (addr);
- if (sym && sym == last_symbol)
- continue;
- last_symbol = sym;
- if (!sym)
- continue;
- dump_usym (prof, sym, addr, 0); /* let's not guess the size */
- //printf ("found symbol at %p: %s\n", (void*)addr, sym);
- }
- }
-}
-
-static int
-mono_cpu_count (void)
-{
-#ifdef PLATFORM_ANDROID
- /* Android tries really hard to save power by powering off CPUs on SMP phones which
- * means the normal way to query cpu count returns a wrong value with userspace API.
- * Instead we use /sys entries to query the actual hardware CPU count.
- */
- int count = 0;
- char buffer[8] = {'\0'};
- int present = open ("/sys/devices/system/cpu/present", O_RDONLY);
- /* Format of the /sys entry is a cpulist of indexes which in the case
- * of present is always of the form "0-(n-1)" when there is more than
- * 1 core, n being the number of CPU cores in the system. Otherwise
- * the value is simply 0
- */
- if (present != -1 && read (present, (char*)buffer, sizeof (buffer)) > 3)
- count = strtol (((char*)buffer) + 2, NULL, 10);
- if (present != -1)
- close (present);
- if (count > 0)
- return count + 1;
-#endif
-
-#if defined(HOST_ARM) || defined (HOST_ARM64)
-
- /* ARM platforms tries really hard to save power by powering off CPUs on SMP phones which
- * means the normal way to query cpu count returns a wrong value with userspace API. */
-
-#ifdef _SC_NPROCESSORS_CONF
- {
- int count = sysconf (_SC_NPROCESSORS_CONF);
- if (count > 0)
- return count;
- }
-#endif
-
-#else
-
-#ifdef HAVE_SCHED_GETAFFINITY
- {
- cpu_set_t set;
- if (sched_getaffinity (getpid (), sizeof (set), &set) == 0)
- return CPU_COUNT (&set);
- }
-#endif
-#ifdef _SC_NPROCESSORS_ONLN
- {
- int count = sysconf (_SC_NPROCESSORS_ONLN);
- if (count > 0)
- return count;
- }
-#endif
-
-#endif /* defined(HOST_ARM) || defined (HOST_ARM64) */
-
-#ifdef USE_SYSCTL
- {
- int count;
- int mib [2];
- size_t len = sizeof (int);
- mib [0] = CTL_HW;
- mib [1] = HW_NCPU;
- if (sysctl (mib, 2, &count, &len, NULL, 0) == 0)
- return count;
- }
-#endif
-#ifdef HOST_WIN32
- {
- SYSTEM_INFO info;
- GetSystemInfo (&info);
- return info.dwNumberOfProcessors;
- }
-#endif
-
- static gboolean warned;
-
- if (!warned) {
- g_warning ("Don't know how to determine CPU count on this platform; assuming 1");
- warned = TRUE;
- }
-
- return 1;
-}
-
-typedef struct MonoCounterAgent {
- MonoCounter *counter;
- // MonoCounterAgent specific data :
- void *value;
- size_t value_size;
- short index;
- short emitted;
- struct MonoCounterAgent *next;
-} MonoCounterAgent;
-
-static MonoCounterAgent* counters;
-static int counters_index = 1;
-static mono_mutex_t counters_mutex;
-
-static void
-counters_add_agent (MonoCounter *counter)
-{
- if (InterlockedRead (&in_shutdown))
- return;
-
- MonoCounterAgent *agent, *item;
-
- mono_os_mutex_lock (&counters_mutex);
-
- for (agent = counters; agent; agent = agent->next) {
- if (agent->counter == counter) {
- agent->value_size = 0;
- if (agent->value) {
- g_free (agent->value);
- agent->value = NULL;
- }
- goto done;
- }
- }
-
- agent = (MonoCounterAgent *) g_malloc (sizeof (MonoCounterAgent));
- agent->counter = counter;
- agent->value = NULL;
- agent->value_size = 0;
- agent->index = counters_index++;
- agent->emitted = 0;
- agent->next = NULL;
-
- if (!counters) {
- counters = agent;
- } else {
- item = counters;
- while (item->next)
- item = item->next;
- item->next = agent;
- }
-
-done:
- mono_os_mutex_unlock (&counters_mutex);
-}
-
-static mono_bool
-counters_init_foreach_callback (MonoCounter *counter, gpointer data)
-{
- counters_add_agent (counter);
- return TRUE;
-}
-
-static void
-counters_init (MonoProfiler *profiler)
-{
- mono_os_mutex_init (&counters_mutex);
-
- mono_counters_on_register (&counters_add_agent);
- mono_counters_foreach (counters_init_foreach_callback, NULL);
-}
-
-static void
-counters_emit (MonoProfiler *profiler)
-{
- MonoCounterAgent *agent;
- int len = 0;
- int size =
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* len */
- ;
-
- mono_os_mutex_lock (&counters_mutex);
-
- for (agent = counters; agent; agent = agent->next) {
- if (agent->emitted)
- continue;
-
- size +=
- LEB128_SIZE /* section */ +
- strlen (mono_counter_get_name (agent->counter)) + 1 /* name */ +
- BYTE_SIZE /* type */ +
- BYTE_SIZE /* unit */ +
- BYTE_SIZE /* variance */ +
- LEB128_SIZE /* index */
- ;
-
- len++;
- }
-
- if (!len)
- goto done;
-
- ENTER_LOG (&counter_descriptors_ctr, logbuffer, size);
-
- emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
- emit_value (logbuffer, len);
-
- for (agent = counters; agent; agent = agent->next) {
- const char *name;
-
- if (agent->emitted)
- continue;
-
- name = mono_counter_get_name (agent->counter);
- emit_value (logbuffer, mono_counter_get_section (agent->counter));
- emit_string (logbuffer, name, strlen (name) + 1);
- emit_byte (logbuffer, mono_counter_get_type (agent->counter));
- emit_byte (logbuffer, mono_counter_get_unit (agent->counter));
- emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
- emit_value (logbuffer, agent->index);
-
- agent->emitted = 1;
- }
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
-done:
- mono_os_mutex_unlock (&counters_mutex);
-}
-
-static void
-counters_sample (MonoProfiler *profiler, uint64_t timestamp)
-{
- MonoCounterAgent *agent;
- MonoCounter *counter;
- int type;
- int buffer_size;
- void *buffer;
- int size;
-
- counters_emit (profiler);
-
- buffer_size = 8;
- buffer = g_calloc (1, buffer_size);
-
- mono_os_mutex_lock (&counters_mutex);
-
- size =
- EVENT_SIZE /* event */
- ;
-
- for (agent = counters; agent; agent = agent->next) {
- size +=
- LEB128_SIZE /* index */ +
- BYTE_SIZE /* type */ +
- mono_counter_get_size (agent->counter) /* value */
- ;
- }
-
- size +=
- LEB128_SIZE /* stop marker */
- ;
-
- ENTER_LOG (&counter_samples_ctr, logbuffer, size);
-
- emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
-
- for (agent = counters; agent; agent = agent->next) {
- size_t size;
-
- counter = agent->counter;
-
- size = mono_counter_get_size (counter);
-
- if (size > buffer_size) {
- buffer_size = size;
- buffer = g_realloc (buffer, buffer_size);
- }
-
- memset (buffer, 0, buffer_size);
-
- g_assert (mono_counters_sample (counter, buffer, size));
-
- type = mono_counter_get_type (counter);
-
- if (!agent->value) {
- agent->value = g_calloc (1, size);
- agent->value_size = size;
- } else {
- if (type == MONO_COUNTER_STRING) {
- if (strcmp (agent->value, buffer) == 0)
- continue;
- } else {
- if (agent->value_size == size && memcmp (agent->value, buffer, size) == 0)
- continue;
- }
- }
-
- emit_uvalue (logbuffer, agent->index);
- emit_byte (logbuffer, type);
- switch (type) {
- case MONO_COUNTER_INT:
-#if SIZEOF_VOID_P == 4
- case MONO_COUNTER_WORD:
-#endif
- emit_svalue (logbuffer, *(int*)buffer - *(int*)agent->value);
- break;
- case MONO_COUNTER_UINT:
- emit_uvalue (logbuffer, *(guint*)buffer - *(guint*)agent->value);
- break;
- case MONO_COUNTER_TIME_INTERVAL:
- case MONO_COUNTER_LONG:
-#if SIZEOF_VOID_P == 8
- case MONO_COUNTER_WORD:
-#endif
- emit_svalue (logbuffer, *(gint64*)buffer - *(gint64*)agent->value);
- break;
- case MONO_COUNTER_ULONG:
- emit_uvalue (logbuffer, *(guint64*)buffer - *(guint64*)agent->value);
- break;
- case MONO_COUNTER_DOUBLE:
- emit_double (logbuffer, *(double*)buffer);
- break;
- case MONO_COUNTER_STRING:
- if (size == 0) {
- emit_byte (logbuffer, 0);
- } else {
- emit_byte (logbuffer, 1);
- emit_string (logbuffer, (char*)buffer, size);
- }
- break;
- default:
- g_assert_not_reached ();
- }
-
- if (type == MONO_COUNTER_STRING && size > agent->value_size) {
- agent->value = g_realloc (agent->value, size);
- agent->value_size = size;
- }
-
- if (size > 0)
- memcpy (agent->value, buffer, size);
- }
- g_free (buffer);
-
- emit_value (logbuffer, 0);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- mono_os_mutex_unlock (&counters_mutex);
-}
-
-typedef struct _PerfCounterAgent PerfCounterAgent;
-struct _PerfCounterAgent {
- PerfCounterAgent *next;
- int index;
- char *category_name;
- char *name;
- int type;
- gint64 value;
- guint8 emitted;
- guint8 updated;
- guint8 deleted;
-};
-
-static PerfCounterAgent *perfcounters = NULL;
-
-static void
-perfcounters_emit (MonoProfiler *profiler)
-{
- PerfCounterAgent *pcagent;
- int len = 0;
- int size =
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* len */
- ;
-
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
- if (pcagent->emitted)
- continue;
-
- size +=
- LEB128_SIZE /* section */ +
- strlen (pcagent->category_name) + 1 /* category name */ +
- strlen (pcagent->name) + 1 /* name */ +
- BYTE_SIZE /* type */ +
- BYTE_SIZE /* unit */ +
- BYTE_SIZE /* variance */ +
- LEB128_SIZE /* index */
- ;
-
- len++;
- }
-
- if (!len)
- return;
-
- ENTER_LOG (&perfcounter_descriptors_ctr, logbuffer, size);
-
- emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
- emit_value (logbuffer, len);
-
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
- if (pcagent->emitted)
- continue;
-
- emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
- emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
- emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
- emit_byte (logbuffer, MONO_COUNTER_LONG);
- emit_byte (logbuffer, MONO_COUNTER_RAW);
- emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
- emit_value (logbuffer, pcagent->index);
-
- pcagent->emitted = 1;
- }
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-static gboolean
-perfcounters_foreach (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data)
-{
- PerfCounterAgent *pcagent;
-
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
- if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
- continue;
- if (pcagent->value == value)
- return TRUE;
-
- pcagent->value = value;
- pcagent->updated = 1;
- pcagent->deleted = 0;
- return TRUE;
- }
-
- pcagent = g_new0 (PerfCounterAgent, 1);
- pcagent->next = perfcounters;
- pcagent->index = counters_index++;
- pcagent->category_name = g_strdup (category_name);
- pcagent->name = g_strdup (name);
- pcagent->type = (int) type;
- pcagent->value = value;
- pcagent->emitted = 0;
- pcagent->updated = 1;
- pcagent->deleted = 0;
-
- perfcounters = pcagent;
-
- return TRUE;
-}
-
-static void
-perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
-{
- PerfCounterAgent *pcagent;
- int len = 0;
- int size;
-
- mono_os_mutex_lock (&counters_mutex);
-
- /* mark all perfcounters as deleted, foreach will unmark them as necessary */
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next)
- pcagent->deleted = 1;
-
- mono_perfcounter_foreach (perfcounters_foreach, perfcounters);
-
- perfcounters_emit (profiler);
-
- size =
- EVENT_SIZE /* event */
- ;
-
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
- if (pcagent->deleted || !pcagent->updated)
- continue;
-
- size +=
- LEB128_SIZE /* index */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* value */
- ;
-
- len++;
- }
-
- if (!len)
- goto done;
-
- size +=
- LEB128_SIZE /* stop marker */
- ;
-
- ENTER_LOG (&perfcounter_samples_ctr, logbuffer, size);
-
- emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
-
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
- if (pcagent->deleted || !pcagent->updated)
- continue;
- emit_uvalue (logbuffer, pcagent->index);
- emit_byte (logbuffer, MONO_COUNTER_LONG);
- emit_svalue (logbuffer, pcagent->value);
-
- pcagent->updated = 0;
- }
-
- emit_value (logbuffer, 0);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
-done:
- mono_os_mutex_unlock (&counters_mutex);
-}
-
-static void
-counters_and_perfcounters_sample (MonoProfiler *prof)
-{
- uint64_t now = current_time ();
-
- counters_sample (prof, now);
- perfcounters_sample (prof, now);
-}
-
-#define COVERAGE_DEBUG(x) if (debug_coverage) {x}
-static mono_mutex_t coverage_mutex;
-static MonoConcurrentHashTable *coverage_methods = NULL;
-static MonoConcurrentHashTable *coverage_assemblies = NULL;
-static MonoConcurrentHashTable *coverage_classes = NULL;
-
-static MonoConcurrentHashTable *filtered_classes = NULL;
-static MonoConcurrentHashTable *entered_methods = NULL;
-static MonoConcurrentHashTable *image_to_methods = NULL;
-static MonoConcurrentHashTable *suppressed_assemblies = NULL;
-static gboolean coverage_initialized = FALSE;
-
-static GPtrArray *coverage_data = NULL;
-static int previous_offset = 0;
-
-typedef struct {
- MonoLockFreeQueueNode node;
- MonoMethod *method;
-} MethodNode;
-
-typedef struct {
- int offset;
- int counter;
- char *filename;
- int line;
- int column;
-} CoverageEntry;
-
-static void
-free_coverage_entry (gpointer data, gpointer userdata)
-{
- CoverageEntry *entry = (CoverageEntry *)data;
- g_free (entry->filename);
- g_free (entry);
-}
-
-static void
-obtain_coverage_for_method (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)
-{
- int offset = entry->iloffset - previous_offset;
- CoverageEntry *e = g_new (CoverageEntry, 1);
-
- previous_offset = entry->iloffset;
-
- e->offset = offset;
- e->counter = entry->counter;
- e->filename = g_strdup(entry->filename ? entry->filename : "");
- e->line = entry->line;
- e->column = entry->col;
-
- g_ptr_array_add (coverage_data, e);
-}
-
-static char *
-parse_generic_type_names(char *name)
-{
- char *new_name, *ret;
- int within_generic_declaration = 0, generic_members = 1;
-
- if (name == NULL || *name == '\0')
- return g_strdup ("");
-
- if (!(ret = new_name = (char *) g_calloc (strlen (name) * 4 + 1, sizeof (char))))
- return NULL;
-
- do {
- switch (*name) {
- case '<':
- within_generic_declaration = 1;
- break;
-
- case '>':
- within_generic_declaration = 0;
-
- if (*(name - 1) != '<') {
- *new_name++ = '`';
- *new_name++ = '0' + generic_members;
- } else {
- memcpy (new_name, "<>", 8);
- new_name += 8;
- }
-
- generic_members = 0;
- break;
-
- case ',':
- generic_members++;
- break;
-
- default:
- if (!within_generic_declaration)
- *new_name++ = *name;
-
- break;
- }
- } while (*name++);
-
- return ret;
-}
-
-static int method_id;
-static void
-build_method_buffer (gpointer key, gpointer value, gpointer userdata)
-{
- MonoMethod *method = (MonoMethod *)value;
- MonoProfiler *prof = (MonoProfiler *)userdata;
- MonoClass *klass;
- MonoImage *image;
- char *class_name;
- const char *image_name, *method_name, *sig, *first_filename;
- guint i;
-
- previous_offset = 0;
- coverage_data = g_ptr_array_new ();
-
- mono_profiler_coverage_get (prof, method, obtain_coverage_for_method);
-
- klass = mono_method_get_class (method);
- image = mono_class_get_image (klass);
- image_name = mono_image_get_name (image);
-
- sig = mono_signature_get_desc (mono_method_signature (method), TRUE);
- class_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));
- method_name = mono_method_get_name (method);
-
- if (coverage_data->len != 0) {
- CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[0];
- first_filename = entry->filename ? entry->filename : "";
- } else
- first_filename = "";
-
- image_name = image_name ? image_name : "";
- sig = sig ? sig : "";
- method_name = method_name ? method_name : "";
-
- ENTER_LOG (&coverage_methods_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- strlen (image_name) + 1 /* image name */ +
- strlen (class_name) + 1 /* class name */ +
- strlen (method_name) + 1 /* method name */ +
- strlen (sig) + 1 /* signature */ +
- strlen (first_filename) + 1 /* first file name */ +
- LEB128_SIZE /* token */ +
- LEB128_SIZE /* method id */ +
- LEB128_SIZE /* entries */
- );
-
- emit_event (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
- emit_string (logbuffer, image_name, strlen (image_name) + 1);
- emit_string (logbuffer, class_name, strlen (class_name) + 1);
- emit_string (logbuffer, method_name, strlen (method_name) + 1);
- emit_string (logbuffer, sig, strlen (sig) + 1);
- emit_string (logbuffer, first_filename, strlen (first_filename) + 1);
-
- emit_uvalue (logbuffer, mono_method_get_token (method));
- emit_uvalue (logbuffer, method_id);
- emit_value (logbuffer, coverage_data->len);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- for (i = 0; i < coverage_data->len; i++) {
- CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[i];
-
- ENTER_LOG (&coverage_statements_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* method id */ +
- LEB128_SIZE /* offset */ +
- LEB128_SIZE /* counter */ +
- LEB128_SIZE /* line */ +
- LEB128_SIZE /* column */
- );
-
- emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
- emit_uvalue (logbuffer, method_id);
- emit_uvalue (logbuffer, entry->offset);
- emit_uvalue (logbuffer, entry->counter);
- emit_uvalue (logbuffer, entry->line);
- emit_uvalue (logbuffer, entry->column);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
- }
-
- method_id++;
-
- g_free (class_name);
-
- g_ptr_array_foreach (coverage_data, free_coverage_entry, NULL);
- g_ptr_array_free (coverage_data, TRUE);
- coverage_data = NULL;
-}
-
-/* This empties the queue */
-static guint
-count_queue (MonoLockFreeQueue *queue)
-{
- MonoLockFreeQueueNode *node;
- guint count = 0;
-
- while ((node = mono_lock_free_queue_dequeue (queue))) {
- count++;
- mono_thread_hazardous_try_free (node, g_free);
- }
-
- return count;
-}
-
-static void
-build_class_buffer (gpointer key, gpointer value, gpointer userdata)
-{
- MonoClass *klass = (MonoClass *)key;
- MonoLockFreeQueue *class_methods = (MonoLockFreeQueue *)value;
- MonoImage *image;
- char *class_name;
- const char *assembly_name;
- int number_of_methods, partially_covered;
- guint fully_covered;
-
- image = mono_class_get_image (klass);
- assembly_name = mono_image_get_name (image);
- class_name = mono_type_get_name (mono_class_get_type (klass));
-
- assembly_name = assembly_name ? assembly_name : "";
- number_of_methods = mono_class_num_methods (klass);
- fully_covered = count_queue (class_methods);
- /* We don't handle partial covered yet */
- partially_covered = 0;
-
- ENTER_LOG (&coverage_classes_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- strlen (assembly_name) + 1 /* assembly name */ +
- strlen (class_name) + 1 /* class name */ +
- LEB128_SIZE /* no. methods */ +
- LEB128_SIZE /* fully covered */ +
- LEB128_SIZE /* partially covered */
- );
-
- emit_event (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
- emit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);
- emit_string (logbuffer, class_name, strlen (class_name) + 1);
- emit_uvalue (logbuffer, number_of_methods);
- emit_uvalue (logbuffer, fully_covered);
- emit_uvalue (logbuffer, partially_covered);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- g_free (class_name);
-}
-
-static void
-get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)
-{
- MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
-
- *number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);
- if (image_methods)
- *fully_covered = count_queue (image_methods);
- else
- *fully_covered = 0;
-
- // FIXME: We don't handle partially covered yet.
- *partially_covered = 0;
-}
-
-static void
-build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)
-{
- MonoAssembly *assembly = (MonoAssembly *)value;
- MonoImage *image = mono_assembly_get_image (assembly);
- const char *name, *guid, *filename;
- int number_of_methods = 0, partially_covered = 0;
- guint fully_covered = 0;
-
- name = mono_image_get_name (image);
- guid = mono_image_get_guid (image);
- filename = mono_image_get_filename (image);
-
- name = name ? name : "";
- guid = guid ? guid : "";
- filename = filename ? filename : "";
-
- get_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);
-
- ENTER_LOG (&coverage_assemblies_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- strlen (name) + 1 /* name */ +
- strlen (guid) + 1 /* guid */ +
- strlen (filename) + 1 /* file name */ +
- LEB128_SIZE /* no. methods */ +
- LEB128_SIZE /* fully covered */ +
- LEB128_SIZE /* partially covered */
- );
-
- emit_event (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
- emit_string (logbuffer, name, strlen (name) + 1);
- emit_string (logbuffer, guid, strlen (guid) + 1);
- emit_string (logbuffer, filename, strlen (filename) + 1);
- emit_uvalue (logbuffer, number_of_methods);
- emit_uvalue (logbuffer, fully_covered);
- emit_uvalue (logbuffer, partially_covered);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-}
-
-static void
-dump_coverage (MonoProfiler *prof)
-{
- if (!coverage_initialized)
- return;
-
- COVERAGE_DEBUG(fprintf (stderr, "Coverage: Started dump\n");)
- method_id = 0;
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_foreach (coverage_assemblies, build_assembly_buffer, NULL);
- mono_conc_hashtable_foreach (coverage_classes, build_class_buffer, NULL);
- mono_conc_hashtable_foreach (coverage_methods, build_method_buffer, prof);
- mono_os_mutex_unlock (&coverage_mutex);
-
- COVERAGE_DEBUG(fprintf (stderr, "Coverage: Finished dump\n");)
-}
-
-static void
-process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method)
-{
- MonoClass *klass;
- MonoImage *image;
-
- if (!coverage_initialized)
- return;
-
- klass = mono_method_get_class (method);
- image = mono_class_get_image (klass);
-
- if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)))
- return;
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (entered_methods, method, method);
- mono_os_mutex_unlock (&coverage_mutex);
-}
-
-static MonoLockFreeQueueNode *
-create_method_node (MonoMethod *method)
-{
- MethodNode *node = (MethodNode *) g_malloc (sizeof (MethodNode));
- mono_lock_free_queue_node_init ((MonoLockFreeQueueNode *) node, FALSE);
- node->method = method;
-
- return (MonoLockFreeQueueNode *) node;
-}
-
-static gboolean
-coverage_filter (MonoProfiler *prof, MonoMethod *method)
-{
- MonoError error;
- MonoClass *klass;
- MonoImage *image;
- MonoAssembly *assembly;
- MonoMethodHeader *header;
- guint32 iflags, flags, code_size;
- char *fqn, *classname;
- gboolean has_positive, found;
- MonoLockFreeQueue *image_methods, *class_methods;
- MonoLockFreeQueueNode *node;
-
- g_assert (coverage_initialized && "Why are we being asked for coverage filter info when we're not doing coverage?");
-
- COVERAGE_DEBUG(fprintf (stderr, "Coverage filter for %s\n", mono_method_get_name (method));)
-
- flags = mono_method_get_flags (method, &iflags);
- if ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) ||
- (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/)) {
- COVERAGE_DEBUG(fprintf (stderr, " Internal call or pinvoke - ignoring\n");)
- return FALSE;
- }
-
- // Don't need to do anything else if we're already tracking this method
- if (mono_conc_hashtable_lookup (coverage_methods, method)) {
- COVERAGE_DEBUG(fprintf (stderr, " Already tracking\n");)
- return TRUE;
- }
-
- klass = mono_method_get_class (method);
- image = mono_class_get_image (klass);
-
- // Don't handle coverage for the core assemblies
- if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
- return FALSE;
-
- if (prof->coverage_filters) {
- /* Check already filtered classes first */
- if (mono_conc_hashtable_lookup (filtered_classes, klass)) {
- COVERAGE_DEBUG(fprintf (stderr, " Already filtered\n");)
- return FALSE;
- }
-
- classname = mono_type_get_name (mono_class_get_type (klass));
-
- fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);
-
- COVERAGE_DEBUG(fprintf (stderr, " Looking for %s in filter\n", fqn);)
- // Check positive filters first
- has_positive = FALSE;
- found = FALSE;
- for (guint i = 0; i < prof->coverage_filters->len; ++i) {
- char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
-
- if (filter [0] == '+') {
- filter = &filter [1];
-
- COVERAGE_DEBUG(fprintf (stderr, " Checking against +%s ...", filter);)
-
- if (strstr (fqn, filter) != NULL) {
- COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
- found = TRUE;
- } else
- COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
-
- has_positive = TRUE;
- }
- }
-
- if (has_positive && !found) {
- COVERAGE_DEBUG(fprintf (stderr, " Positive match was not found\n");)
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (filtered_classes, klass, klass);
- mono_os_mutex_unlock (&coverage_mutex);
- g_free (fqn);
- g_free (classname);
-
- return FALSE;
- }
-
- for (guint i = 0; i < prof->coverage_filters->len; ++i) {
- // FIXME: Is substring search sufficient?
- char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
- if (filter [0] == '+')
- continue;
-
- // Skip '-'
- filter = &filter [1];
- COVERAGE_DEBUG(fprintf (stderr, " Checking against -%s ...", filter);)
-
- if (strstr (fqn, filter) != NULL) {
- COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (filtered_classes, klass, klass);
- mono_os_mutex_unlock (&coverage_mutex);
- g_free (fqn);
- g_free (classname);
-
- return FALSE;
- } else
- COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
-
- }
-
- g_free (fqn);
- g_free (classname);
- }
-
- COVERAGE_DEBUG(fprintf (stderr, " Handling coverage for %s\n", mono_method_get_name (method));)
- header = mono_method_get_header_checked (method, &error);
- mono_error_cleanup (&error);
-
- mono_method_header_get_code (header, &code_size, NULL);
-
- assembly = mono_image_get_assembly (image);
-
- // Need to keep the assemblies around for as long as they are kept in the hashtable
- // Nunit, for example, has a habit of unloading them before the coverage statistics are
- // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
- mono_assembly_addref (assembly);
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (coverage_methods, method, method);
- mono_conc_hashtable_insert (coverage_assemblies, assembly, assembly);
- mono_os_mutex_unlock (&coverage_mutex);
-
- image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
-
- if (image_methods == NULL) {
- image_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
- mono_lock_free_queue_init (image_methods);
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (image_to_methods, image, image_methods);
- mono_os_mutex_unlock (&coverage_mutex);
- }
-
- node = create_method_node (method);
- mono_lock_free_queue_enqueue (image_methods, node);
-
- class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (coverage_classes, klass);
-
- if (class_methods == NULL) {
- class_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
- mono_lock_free_queue_init (class_methods);
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (coverage_classes, klass, class_methods);
- mono_os_mutex_unlock (&coverage_mutex);
- }
-
- node = create_method_node (method);
- mono_lock_free_queue_enqueue (class_methods, node);
-
- return TRUE;
-}
-
-#define LINE_BUFFER_SIZE 4096
-/* Max file limit of 128KB */
-#define MAX_FILE_SIZE 128 * 1024
-static char *
-get_file_content (FILE *stream)
-{
- char *buffer;
- ssize_t bytes_read;
- long filesize;
- int res, offset = 0;
-
- res = fseek (stream, 0, SEEK_END);
- if (res < 0)
- return NULL;
-
- filesize = ftell (stream);
- if (filesize < 0)
- return NULL;
-
- res = fseek (stream, 0, SEEK_SET);
- if (res < 0)
- return NULL;
-
- if (filesize > MAX_FILE_SIZE)
- return NULL;
-
- buffer = (char *) g_malloc ((filesize + 1) * sizeof (char));
- while ((bytes_read = fread (buffer + offset, 1, LINE_BUFFER_SIZE, stream)) > 0)
- offset += bytes_read;
-
- /* NULL terminate our buffer */
- buffer[filesize] = '\0';
- return buffer;
-}
-
-static char *
-get_next_line (char *contents, char **next_start)
-{
- char *p = contents;
-
- if (p == NULL || *p == '\0') {
- *next_start = NULL;
- return NULL;
- }
-
- while (*p != '\n' && *p != '\0')
- p++;
-
- if (*p == '\n') {
- *p = '\0';
- *next_start = p + 1;
- } else
- *next_start = NULL;
-
- return contents;
-}
-
-static void
-init_suppressed_assemblies (void)
-{
- char *content;
- char *line;
- FILE *sa_file;
-
- suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
- sa_file = fopen (SUPPRESSION_DIR "/mono-profiler-log.suppression", "r");
- if (sa_file == NULL)
- return;
-
- /* Don't need to free @content as it is referred to by the lines stored in @suppressed_assemblies */
- content = get_file_content (sa_file);
- if (content == NULL) {
- g_error ("mono-profiler-log.suppression is greater than 128kb - aborting\n");
- }
-
- while ((line = get_next_line (content, &content))) {
- line = g_strchomp (g_strchug (line));
- /* No locking needed as we're doing initialization */
- mono_conc_hashtable_insert (suppressed_assemblies, line, line);
- }
-
- fclose (sa_file);
-}
-
-static void
-coverage_init (MonoProfiler *prof)
-{
- g_assert (!coverage_initialized && "Why are we initializing coverage twice?");
-
- COVERAGE_DEBUG(fprintf (stderr, "Coverage initialized\n");)
-
- mono_os_mutex_init (&coverage_mutex);
- coverage_methods = mono_conc_hashtable_new (NULL, NULL);
- coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
- coverage_classes = mono_conc_hashtable_new (NULL, NULL);
- filtered_classes = mono_conc_hashtable_new (NULL, NULL);
- entered_methods = mono_conc_hashtable_new (NULL, NULL);
- image_to_methods = mono_conc_hashtable_new (NULL, NULL);
- init_suppressed_assemblies ();
-
- coverage_initialized = TRUE;
-}
-
-static void
-unref_coverage_assemblies (gpointer key, gpointer value, gpointer userdata)
-{
- MonoAssembly *assembly = (MonoAssembly *)value;
- mono_assembly_close (assembly);
-}
-
-static void
-free_sample_hit (gpointer p)
-{
- mono_lock_free_free (p, SAMPLE_BLOCK_SIZE);
-}
-
-static void
-cleanup_reusable_samples (MonoProfiler *prof)
-{
- SampleHit *sample;
-
- while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->sample_reuse_queue)))
- mono_thread_hazardous_try_free (sample, free_sample_hit);
-}
-
-static void
-log_shutdown (MonoProfiler *prof)
-{
- InterlockedWrite (&in_shutdown, 1);
-
- if (!no_counters)
- counters_and_perfcounters_sample (prof);
-
- dump_coverage (prof);
-
- char c = 1;
-
- if (write (prof->pipes [1], &c, 1) != 1) {
- fprintf (stderr, "Could not write to pipe: %s\n", strerror (errno));
- exit (1);
- }
-
- mono_native_thread_join (prof->helper_thread);
-
- mono_os_mutex_destroy (&counters_mutex);
-
- MonoCounterAgent *mc_next;
-
- for (MonoCounterAgent *cur = counters; cur; cur = mc_next) {
- mc_next = cur->next;
- g_free (cur);
- }
-
- PerfCounterAgent *pc_next;
-
- for (PerfCounterAgent *cur = perfcounters; cur; cur = pc_next) {
- pc_next = cur->next;
- g_free (cur);
- }
-
- /*
- * Ensure that we empty the LLS completely, even if some nodes are
- * not immediately removed upon calling mono_lls_remove (), by
- * iterating until the head is NULL.
- */
- while (profiler_thread_list.head) {
- MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
- g_assert (thread->attached && "Why is a thread in the LLS not attached?");
-
- remove_thread (thread);
- } MONO_LLS_FOREACH_SAFE_END
- }
-
- /*
- * Ensure that all threads have been freed, so that we don't miss any
- * buffers when we shut down the writer thread below.
- */
- mono_thread_hazardous_try_free_all ();
-
- InterlockedWrite (&prof->run_dumper_thread, 0);
- mono_os_sem_post (&prof->dumper_queue_sem);
- mono_native_thread_join (prof->dumper_thread);
- mono_os_sem_destroy (&prof->dumper_queue_sem);
-
- InterlockedWrite (&prof->run_writer_thread, 0);
- mono_os_sem_post (&prof->writer_queue_sem);
- mono_native_thread_join (prof->writer_thread);
- mono_os_sem_destroy (&prof->writer_queue_sem);
-
- /*
- * Free all writer queue entries, and ensure that all sample hits will be
- * added to the sample reuse queue.
- */
- mono_thread_hazardous_try_free_all ();
-
- cleanup_reusable_samples (prof);
-
- /*
- * Finally, make sure that all sample hits are freed. This should cover all
- * hazardous data from the profiler. We can now be sure that the runtime
- * won't later invoke free functions in the profiler library after it has
- * been unloaded.
- */
- mono_thread_hazardous_try_free_all ();
-
- g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why is the reader count still non-zero?");
- g_assert (!InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why does someone still hold the exclusive lock?");
-
-#if defined (HAVE_SYS_ZLIB)
- if (prof->gzfile)
- gzclose (prof->gzfile);
-#endif
- if (prof->pipe_output)
- pclose (prof->file);
- else
- fclose (prof->file);
-
- mono_conc_hashtable_destroy (prof->method_table);
- mono_os_mutex_destroy (&prof->method_table_mutex);
-
- if (coverage_initialized) {
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_foreach (coverage_assemblies, unref_coverage_assemblies, prof);
- mono_os_mutex_unlock (&coverage_mutex);
-
- mono_conc_hashtable_destroy (coverage_methods);
- mono_conc_hashtable_destroy (coverage_assemblies);
- mono_conc_hashtable_destroy (coverage_classes);
- mono_conc_hashtable_destroy (filtered_classes);
-
- mono_conc_hashtable_destroy (entered_methods);
- mono_conc_hashtable_destroy (image_to_methods);
- mono_conc_hashtable_destroy (suppressed_assemblies);
- mono_os_mutex_destroy (&coverage_mutex);
- }
-
- PROF_TLS_FREE ();
-
- g_free (prof->args);
- g_free (prof);
-}
-
-static char*
-new_filename (const char* filename)
-{
- time_t t = time (NULL);
- int pid = process_id ();
- char pid_buf [16];
- char time_buf [16];
- char *res, *d;
- const char *p;
- int count_dates = 0;
- int count_pids = 0;
- int s_date, s_pid;
- struct tm *ts;
- for (p = filename; *p; p++) {
- if (*p != '%')
- continue;
- p++;
- if (*p == 't')
- count_dates++;
- else if (*p == 'p')
- count_pids++;
- else if (*p == 0)
- break;
- }
- if (!count_dates && !count_pids)
- return pstrdup (filename);
- snprintf (pid_buf, sizeof (pid_buf), "%d", pid);
- ts = gmtime (&t);
- snprintf (time_buf, sizeof (time_buf), "%d%02d%02d%02d%02d%02d",
- 1900 + ts->tm_year, 1 + ts->tm_mon, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
- s_date = strlen (time_buf);
- s_pid = strlen (pid_buf);
- d = res = (char *) g_malloc (strlen (filename) + s_date * count_dates + s_pid * count_pids);
- for (p = filename; *p; p++) {
- if (*p != '%') {
- *d++ = *p;
- continue;
- }
- p++;
- if (*p == 't') {
- strcpy (d, time_buf);
- d += s_date;
- continue;
- } else if (*p == 'p') {
- strcpy (d, pid_buf);
- d += s_pid;
- continue;
- } else if (*p == '%') {
- *d++ = '%';
- continue;
- } else if (*p == 0)
- break;
- *d++ = '%';
- *d++ = *p;
- }
- *d = 0;
- return res;
-}
-
-static void
-add_to_fd_set (fd_set *set, int fd, int *max_fd)
-{
- /*
- * This should only trigger for the basic FDs (server socket, pipes) at
- * startup if for some mysterious reason they're too large. In this case,
- * the profiler really can't function, and we're better off printing an
- * error and exiting.
- */
- if (fd >= FD_SETSIZE) {
- fprintf (stderr, "File descriptor is out of bounds for fd_set: %d\n", fd);
- exit (1);
- }
-
- FD_SET (fd, set);
-
- if (*max_fd < fd)
- *max_fd = fd;
-}
-
-static void *
-helper_thread (void *arg)
-{
- MonoProfiler *prof = (MonoProfiler *) arg;
-
- mono_threads_attach_tools_thread ();
- mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
-
- MonoProfilerThread *thread = init_thread (prof, FALSE);
-
- GArray *command_sockets = g_array_new (FALSE, FALSE, sizeof (int));
-
- while (1) {
- fd_set rfds;
- int max_fd = -1;
-
- FD_ZERO (&rfds);
-
- add_to_fd_set (&rfds, prof->server_socket, &max_fd);
- add_to_fd_set (&rfds, prof->pipes [0], &max_fd);
-
- for (gint i = 0; i < command_sockets->len; i++)
- add_to_fd_set (&rfds, g_array_index (command_sockets, int, i), &max_fd);
-
- struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
-
- // Sleep for 1sec or until a file descriptor has data.
- if (select (max_fd + 1, &rfds, NULL, NULL, &tv) == -1) {
- if (errno == EINTR)
- continue;
-
- fprintf (stderr, "Error in mono-profiler-log server: %s", strerror (errno));
- exit (1);
- }
-
- if (!no_counters)
- counters_and_perfcounters_sample (prof);
-
- buffer_lock_excl ();
-
- sync_point (SYNC_POINT_PERIODIC);
-
- buffer_unlock_excl ();
-
- // Are we shutting down?
- if (FD_ISSET (prof->pipes [0], &rfds)) {
- char c;
- read (prof->pipes [0], &c, 1);
- break;
- }
-
- for (gint i = 0; i < command_sockets->len; i++) {
- int fd = g_array_index (command_sockets, int, i);
-
- if (!FD_ISSET (fd, &rfds))
- continue;
-
- char buf [64];
- int len = read (fd, buf, sizeof (buf) - 1);
-
- if (len == -1)
- continue;
-
- if (!len) {
- // The other end disconnected.
- g_array_remove_index (command_sockets, i);
- close (fd);
-
- continue;
- }
-
- buf [len] = 0;
-
- if (!strcmp (buf, "heapshot\n") && hs_mode_ondemand) {
- // Rely on the finalization callbacks invoking process_requests ().
- heapshot_requested = 1;
- mono_gc_finalize_notify ();
- }
- }
-
- if (FD_ISSET (prof->server_socket, &rfds)) {
- int fd = accept (prof->server_socket, NULL, NULL);
-
- if (fd != -1) {
- if (fd >= FD_SETSIZE)
- close (fd);
- else
- g_array_append_val (command_sockets, fd);
- }
- }
- }
-
- for (gint i = 0; i < command_sockets->len; i++)
- close (g_array_index (command_sockets, int, i));
-
- g_array_free (command_sockets, TRUE);
-
- send_log_unsafe (FALSE);
- deinit_thread (thread);
-
- mono_thread_info_detach ();
-
- return NULL;
-}
-
-static void
-start_helper_thread (MonoProfiler* prof)
-{
- if (pipe (prof->pipes) == -1) {
- fprintf (stderr, "Cannot create pipe: %s\n", strerror (errno));
- exit (1);
- }
-
- prof->server_socket = socket (PF_INET, SOCK_STREAM, 0);
-
- if (prof->server_socket == -1) {
- fprintf (stderr, "Cannot create server socket: %s\n", strerror (errno));
- exit (1);
- }
-
- struct sockaddr_in server_address;
-
- memset (&server_address, 0, sizeof (server_address));
- server_address.sin_family = AF_INET;
- server_address.sin_addr.s_addr = INADDR_ANY;
- server_address.sin_port = htons (prof->command_port);
-
- if (bind (prof->server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
- fprintf (stderr, "Cannot bind server socket on port %d: %s\n", prof->command_port, strerror (errno));
- close (prof->server_socket);
- exit (1);
- }
-
- if (listen (prof->server_socket, 1) == -1) {
- fprintf (stderr, "Cannot listen on server socket: %s\n", strerror (errno));
- close (prof->server_socket);
- exit (1);
- }
-
- socklen_t slen = sizeof (server_address);
-
- if (getsockname (prof->server_socket, (struct sockaddr *) &server_address, &slen)) {
- fprintf (stderr, "Could not get assigned port: %s\n", strerror (errno));
- close (prof->server_socket);
- exit (1);
- }
-
- prof->command_port = ntohs (server_address.sin_port);
-
- if (!mono_native_thread_create (&prof->helper_thread, helper_thread, prof)) {
- fprintf (stderr, "Could not start helper thread\n");
- close (prof->server_socket);
- exit (1);
- }
-}
-
-static void
-free_writer_entry (gpointer p)
-{
- mono_lock_free_free (p, WRITER_ENTRY_BLOCK_SIZE);
-}
-
-static gboolean
-handle_writer_queue_entry (MonoProfiler *prof)
-{
- WriterQueueEntry *entry;
-
- if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&prof->writer_queue))) {
- if (!entry->methods)
- goto no_methods;
-
- gboolean wrote_methods = FALSE;
-
- /*
- * Encode the method events in a temporary log buffer that we
- * flush to disk before the main buffer, ensuring that all
- * methods have metadata emitted before they're referenced.
- *
- * We use a 'proper' thread-local buffer for this as opposed
- * to allocating and freeing a buffer by hand because the call
- * to mono_method_full_name () below may trigger class load
- * events when it retrieves the signature of the method. So a
- * thread-local buffer needs to exist when such events occur.
- */
- for (guint i = 0; i < entry->methods->len; i++) {
- MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
-
- if (mono_conc_hashtable_lookup (prof->method_table, info->method))
- goto free_info; // This method already has metadata emitted.
-
- /*
- * Other threads use this hash table to get a general
- * idea of whether a method has already been emitted to
- * the stream. Due to the way we add to this table, it
- * can easily happen that multiple threads queue up the
- * same methods, but that's OK since eventually all
- * methods will be in this table and the thread-local
- * method lists will just be empty for the rest of the
- * app's lifetime.
- */
- mono_os_mutex_lock (&prof->method_table_mutex);
- mono_conc_hashtable_insert (prof->method_table, info->method, info->method);
- mono_os_mutex_unlock (&prof->method_table_mutex);
-
- char *name = mono_method_full_name (info->method, 1);
- int nlen = strlen (name) + 1;
- void *cstart = info->ji ? mono_jit_info_get_code_start (info->ji) : NULL;
- int csize = info->ji ? mono_jit_info_get_code_size (info->ji) : 0;
-
- ENTER_LOG (&method_jits_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* method */ +
- LEB128_SIZE /* start */ +
- LEB128_SIZE /* size */ +
- nlen /* name */
- );
-
- emit_event_time (logbuffer, TYPE_JIT | TYPE_METHOD, info->time);
- emit_method_inner (logbuffer, info->method);
- emit_ptr (logbuffer, cstart);
- emit_value (logbuffer, csize);
-
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG_EXPLICIT (NO_SEND, NO_REQUESTS);
-
- mono_free (name);
-
- wrote_methods = TRUE;
-
- free_info:
- g_free (info);
- }
-
- g_ptr_array_free (entry->methods, TRUE);
-
- if (wrote_methods) {
- dump_buffer_threadless (prof, PROF_TLS_GET ()->buffer);
- init_buffer_state (PROF_TLS_GET ());
- }
-
- no_methods:
- dump_buffer (prof, entry->buffer);
-
- mono_thread_hazardous_try_free (entry, free_writer_entry);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void *
-writer_thread (void *arg)
-{
- MonoProfiler *prof = (MonoProfiler *)arg;
-
- mono_threads_attach_tools_thread ();
- mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler writer");
-
- dump_header (prof);
-
- MonoProfilerThread *thread = init_thread (prof, FALSE);
-
- while (InterlockedRead (&prof->run_writer_thread)) {
- mono_os_sem_wait (&prof->writer_queue_sem, MONO_SEM_FLAGS_NONE);
- handle_writer_queue_entry (prof);
- }
-
- /* Drain any remaining entries on shutdown. */
- while (handle_writer_queue_entry (prof));
-
- free_buffer (thread->buffer, thread->buffer->size);
- deinit_thread (thread);
-
- mono_thread_info_detach ();
-
- return NULL;
-}
-
-static void
-start_writer_thread (MonoProfiler* prof)
-{
- InterlockedWrite (&prof->run_writer_thread, 1);
-
- if (!mono_native_thread_create (&prof->writer_thread, writer_thread, prof)) {
- fprintf (stderr, "Could not start writer thread\n");
- exit (1);
- }
-}
-
-static void
-reuse_sample_hit (gpointer p)
-{
- SampleHit *sample = p;
-
- mono_lock_free_queue_node_unpoison (&sample->node);
- mono_lock_free_queue_enqueue (&sample->prof->sample_reuse_queue, &sample->node);
-}
-
-static gboolean
-handle_dumper_queue_entry (MonoProfiler *prof)
-{
- SampleHit *sample;
-
- if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->dumper_queue))) {
- for (int i = 0; i < sample->count; ++i) {
- MonoMethod *method = sample->frames [i].method;
- MonoDomain *domain = sample->frames [i].domain;
- void *address = sample->frames [i].base_address;
-
- if (!method) {
- g_assert (domain && "What happened to the domain pointer?");
- g_assert (address && "What happened to the instruction pointer?");
-
- MonoJitInfo *ji = mono_jit_info_table_find (domain, (char *) address);
-
- if (ji)
- sample->frames [i].method = mono_jit_info_get_method (ji);
- }
- }
-
- ENTER_LOG (&sample_hits_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* tid */ +
- LEB128_SIZE /* count */ +
- 1 * (
- LEB128_SIZE /* ip */
- ) +
- LEB128_SIZE /* managed count */ +
- sample->count * (
- LEB128_SIZE /* method */
- )
- );
-
- emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
- emit_byte (logbuffer, SAMPLE_CYCLES);
- emit_ptr (logbuffer, (void *) sample->tid);
- emit_value (logbuffer, 1);
-
- // TODO: Actual native unwinding.
- for (int i = 0; i < 1; ++i) {
- emit_ptr (logbuffer, sample->ip);
- add_code_pointer ((uintptr_t) sample->ip);
- }
-
- /* new in data version 6 */
- emit_uvalue (logbuffer, sample->count);
-
- for (int i = 0; i < sample->count; ++i)
- emit_method (logbuffer, sample->frames [i].method);
-
- EXIT_LOG_EXPLICIT (DO_SEND, NO_REQUESTS);
-
- mono_thread_hazardous_try_free (sample, reuse_sample_hit);
-
- dump_unmanaged_coderefs (prof);
- }
-
- return FALSE;
-}
-
-static void *
-dumper_thread (void *arg)
-{
- MonoProfiler *prof = (MonoProfiler *)arg;
-
- mono_threads_attach_tools_thread ();
- mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
-
- MonoProfilerThread *thread = init_thread (prof, FALSE);
-
- while (InterlockedRead (&prof->run_dumper_thread)) {
- mono_os_sem_wait (&prof->dumper_queue_sem, MONO_SEM_FLAGS_NONE);
- handle_dumper_queue_entry (prof);
- }
-
- /* Drain any remaining entries on shutdown. */
- while (handle_dumper_queue_entry (prof));
-
- send_log_unsafe (FALSE);
- deinit_thread (thread);
-
- mono_thread_info_detach ();
-
- return NULL;
-}
-
-static void
-start_dumper_thread (MonoProfiler* prof)
-{
- InterlockedWrite (&prof->run_dumper_thread, 1);
-
- if (!mono_native_thread_create (&prof->dumper_thread, dumper_thread, prof)) {
- fprintf (stderr, "Could not start dumper thread\n");
- exit (1);
- }
-}
-
-static void
-register_counter (const char *name, gint32 *counter)
-{
- mono_counters_register (name, MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, counter);
-}
-
-static void
-runtime_initialized (MonoProfiler *profiler)
-{
- InterlockedWrite (&runtime_inited, 1);
-
- register_counter ("Sample events allocated", &sample_allocations_ctr);
- register_counter ("Log buffers allocated", &buffer_allocations_ctr);
-
- register_counter ("Event: Sync points", &sync_points_ctr);
- register_counter ("Event: Heap objects", &heap_objects_ctr);
- register_counter ("Event: Heap starts", &heap_starts_ctr);
- register_counter ("Event: Heap ends", &heap_ends_ctr);
- register_counter ("Event: Heap roots", &heap_roots_ctr);
- register_counter ("Event: GC events", &gc_events_ctr);
- register_counter ("Event: GC resizes", &gc_resizes_ctr);
- register_counter ("Event: GC allocations", &gc_allocs_ctr);
- register_counter ("Event: GC moves", &gc_moves_ctr);
- register_counter ("Event: GC handle creations", &gc_handle_creations_ctr);
- register_counter ("Event: GC handle deletions", &gc_handle_deletions_ctr);
- register_counter ("Event: GC finalize starts", &finalize_begins_ctr);
- register_counter ("Event: GC finalize ends", &finalize_ends_ctr);
- register_counter ("Event: GC finalize object starts", &finalize_object_begins_ctr);
- register_counter ("Event: GC finalize object ends", &finalize_object_ends_ctr);
- register_counter ("Event: Image loads", &image_loads_ctr);
- register_counter ("Event: Image unloads", &image_unloads_ctr);
- register_counter ("Event: Assembly loads", &assembly_loads_ctr);
- register_counter ("Event: Assembly unloads", &assembly_unloads_ctr);
- register_counter ("Event: Class loads", &class_loads_ctr);
- register_counter ("Event: Class unloads", &class_unloads_ctr);
- register_counter ("Event: Method entries", &method_entries_ctr);
- register_counter ("Event: Method exits", &method_exits_ctr);
- register_counter ("Event: Method exception leaves", &method_exception_exits_ctr);
- register_counter ("Event: Method JITs", &method_jits_ctr);
- register_counter ("Event: Code buffers", &code_buffers_ctr);
- register_counter ("Event: Exception throws", &exception_throws_ctr);
- register_counter ("Event: Exception clauses", &exception_clauses_ctr);
- register_counter ("Event: Monitor contentions", &monitor_contentions_ctr);
- register_counter ("Event: Monitor acquisitions", &monitor_acquisitions_ctr);
- register_counter ("Event: Monitor failures", &monitor_failures_ctr);
- register_counter ("Event: Thread starts", &thread_starts_ctr);
- register_counter ("Event: Thread ends", &thread_ends_ctr);
- register_counter ("Event: Thread names", &thread_names_ctr);
- register_counter ("Event: Domain loads", &domain_loads_ctr);
- register_counter ("Event: Domain unloads", &domain_unloads_ctr);
- register_counter ("Event: Domain names", &domain_names_ctr);
- register_counter ("Event: Context loads", &context_loads_ctr);
- register_counter ("Event: Context unloads", &context_unloads_ctr);
- register_counter ("Event: Sample binaries", &sample_ubins_ctr);
- register_counter ("Event: Sample symbols", &sample_usyms_ctr);
- register_counter ("Event: Sample hits", &sample_hits_ctr);
- register_counter ("Event: Counter descriptors", &counter_descriptors_ctr);
- register_counter ("Event: Counter samples", &counter_samples_ctr);
- register_counter ("Event: Performance counter descriptors", &perfcounter_descriptors_ctr);
- register_counter ("Event: Performance counter samples", &perfcounter_samples_ctr);
- register_counter ("Event: Coverage methods", &coverage_methods_ctr);
- register_counter ("Event: Coverage statements", &coverage_statements_ctr);
- register_counter ("Event: Coverage classes", &coverage_classes_ctr);
- register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr);
-
- counters_init (profiler);
-
- /*
- * We must start the helper thread before the writer thread. This is
- * because the helper thread sets up the command port which is written to
- * the log header by the writer thread.
- */
- start_helper_thread (profiler);
- start_writer_thread (profiler);
- start_dumper_thread (profiler);
-}
-
-static MonoProfiler*
-create_profiler (const char *args, const char *filename, GPtrArray *filters)
-{
- MonoProfiler *prof;
- char *nf;
- int force_delete = 0;
- prof = (MonoProfiler *) g_calloc (1, sizeof (MonoProfiler));
-
- prof->args = pstrdup (args);
- prof->command_port = command_port;
- if (filename && *filename == '-') {
- force_delete = 1;
- filename++;
- }
- if (!filename) {
- if (do_report)
- filename = "|mprof-report -";
- else
- filename = "output.mlpd";
- nf = (char*)filename;
- } else {
- nf = new_filename (filename);
- if (do_report) {
- int s = strlen (nf) + 32;
- char *p = (char *) g_malloc (s);
- snprintf (p, s, "|mprof-report '--out=%s' -", nf);
- g_free (nf);
- nf = p;
- }
- }
- if (*nf == '|') {
- prof->file = popen (nf + 1, "w");
- prof->pipe_output = 1;
- } else if (*nf == '#') {
- int fd = strtol (nf + 1, NULL, 10);
- prof->file = fdopen (fd, "a");
- } else {
- if (force_delete)
- unlink (nf);
- prof->file = fopen (nf, "wb");
- }
- if (!prof->file) {
- fprintf (stderr, "Cannot create profiler output: %s\n", nf);
- exit (1);
- }
-
-#if defined (HAVE_SYS_ZLIB)
- if (use_zip)
- prof->gzfile = gzdopen (fileno (prof->file), "wb");
-#endif
-
- /*
- * If you hit this assert while increasing MAX_FRAMES, you need to increase
- * SAMPLE_BLOCK_SIZE as well.
- */
- g_assert (SAMPLE_SLOT_SIZE (MAX_FRAMES) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (SAMPLE_BLOCK_SIZE));
-
- // FIXME: We should free this stuff too.
- mono_lock_free_allocator_init_size_class (&prof->sample_size_class, SAMPLE_SLOT_SIZE (num_frames), SAMPLE_BLOCK_SIZE);
- mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
-
- mono_lock_free_queue_init (&prof->sample_reuse_queue);
-
- g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
-
- // FIXME: We should free this stuff too.
- mono_lock_free_allocator_init_size_class (&prof->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
- mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
-
- mono_lock_free_queue_init (&prof->writer_queue);
- mono_os_sem_init (&prof->writer_queue_sem, 0);
-
- mono_lock_free_queue_init (&prof->dumper_queue);
- mono_os_sem_init (&prof->dumper_queue_sem, 0);
-
- mono_os_mutex_init (&prof->method_table_mutex);
- prof->method_table = mono_conc_hashtable_new (NULL, NULL);
-
- if (do_coverage)
- coverage_init (prof);
- prof->coverage_filters = filters;
-
- prof->startup_time = current_time ();
- return prof;
-}
-
-static void
-usage (int do_exit)
-{
- printf ("Log profiler version %d.%d (format: %d)\n", LOG_VERSION_MAJOR, LOG_VERSION_MINOR, LOG_DATA_VERSION);
- printf ("Usage: mono --profile=log[:OPTION1[,OPTION2...]] program.exe\n");
- printf ("Options:\n");
- printf ("\thelp show this usage info\n");
- printf ("\t[no]alloc enable/disable recording allocation info\n");
- printf ("\t[no]calls enable/disable recording enter/leave method events\n");
- printf ("\theapshot[=MODE] record heap shot info (by default at each major collection)\n");
- printf ("\t MODE: every XXms milliseconds, every YYgc collections, ondemand\n");
- printf ("\tcounters sample counters every 1s\n");
- printf ("\tsample[=TYPE] use statistical sampling mode (by default cycles/100)\n");
- printf ("\t TYPE: cycles,instr,cacherefs,cachemiss,branches,branchmiss\n");
- printf ("\t TYPE can be followed by /FREQUENCY\n");
- printf ("\tmaxframes=NUM collect up to NUM stack frames\n");
- printf ("\tcalldepth=NUM ignore method events for call chain depth bigger than NUM\n");
- printf ("\toutput=FILENAME write the data to file FILENAME (-FILENAME to overwrite)\n");
- printf ("\toutput=|PROGRAM write the data to the stdin of PROGRAM\n");
- printf ("\t %%t is subtituted with date and time, %%p with the pid\n");
- printf ("\treport create a report instead of writing the raw data to a file\n");
- printf ("\tzip compress the output data\n");
- printf ("\tport=PORTNUM use PORTNUM for the listening command server\n");
- printf ("\tcoverage enable collection of code coverage data\n");
- printf ("\tcovfilter=ASSEMBLY add an assembly to the code coverage filters\n");
- printf ("\t add a + to include the assembly or a - to exclude it\n");
- printf ("\t filter=-mscorlib\n");
- printf ("\tcovfilter-file=FILE use FILE to generate the list of assemblies to be filtered\n");
- if (do_exit)
- exit (1);
-}
-
-static const char*
-match_option (const char* p, const char *opt, char **rval)
-{
- int len = strlen (opt);
- if (strncmp (p, opt, len) == 0) {
- if (rval) {
- if (p [len] == '=' && p [len + 1]) {
- const char *opt = p + len + 1;
- const char *end = strchr (opt, ',');
- char *val;
- int l;
- if (end == NULL) {
- l = strlen (opt);
- } else {
- l = end - opt;
- }
- val = (char *) g_malloc (l + 1);
- memcpy (val, opt, l);
- val [l] = 0;
- *rval = val;
- return opt + l;
- }
- if (p [len] == 0 || p [len] == ',') {
- *rval = NULL;
- return p + len + (p [len] == ',');
- }
- usage (1);
- } else {
- if (p [len] == 0)
- return p + len;
- if (p [len] == ',')
- return p + len + 1;
- }
- }
- return p;
-}
-
-static void
-set_sample_freq (char *val)
-{
- do_mono_sample = 1;
- sample_freq = 100;
-
- if (!val)
- return;
-
- char *p = val;
-
- // Is it only the frequency (new option style)?
- if (isdigit (*p))
- goto parse;
-
- // Skip the sample type for backwards compatibility.
- while (isalpha (*p))
- p++;
-
- // Skip the forward slash only if we got a sample type.
- if (p != val && *p == '/') {
- p++;
-
- char *end;
-
- parse:
- sample_freq = strtoul (p, &end, 10);
-
- if (p == end)
- usage (1);
-
- p = end;
- }
-
- if (*p)
- usage (1);
-
- g_free (val);
-}
-
-static void
-set_hsmode (char* val, int allow_empty)
-{
- char *end;
- unsigned int count;
- if (allow_empty && !val)
- return;
- if (strcmp (val, "ondemand") == 0) {
- hs_mode_ondemand = 1;
- g_free (val);
- return;
- }
- count = strtoul (val, &end, 10);
- if (val == end)
- usage (1);
- if (strcmp (end, "ms") == 0)
- hs_mode_ms = count;
- else if (strcmp (end, "gc") == 0)
- hs_mode_gc = count;
- else
- usage (1);
- g_free (val);
-}
-
-/*
- * declaration to silence the compiler: this is the entry point that
- * mono will load from the shared library and call.
- */
-extern void
-mono_profiler_startup (const char *desc);
-
-extern void
-mono_profiler_startup_log (const char *desc);
-
-/*
- * this is the entry point that will be used when the profiler
- * is embedded inside the main executable.
- */
-void
-mono_profiler_startup_log (const char *desc)
-{
- mono_profiler_startup (desc);
-}
-
-void
-mono_profiler_startup (const char *desc)
-{
- MonoProfiler *prof;
- GPtrArray *filters = NULL;
- char *filename = NULL;
- const char *p;
- const char *opt;
- int calls_enabled = 0;
- int allocs_enabled = 0;
- int events = MONO_PROFILE_GC|MONO_PROFILE_ALLOCATIONS|
- MONO_PROFILE_GC_MOVES|MONO_PROFILE_CLASS_EVENTS|MONO_PROFILE_THREADS|
- MONO_PROFILE_ENTER_LEAVE|MONO_PROFILE_JIT_COMPILATION|MONO_PROFILE_EXCEPTIONS|
- MONO_PROFILE_MONITOR_EVENTS|MONO_PROFILE_MODULE_EVENTS|MONO_PROFILE_GC_ROOTS|
- MONO_PROFILE_INS_COVERAGE|MONO_PROFILE_APPDOMAIN_EVENTS|MONO_PROFILE_CONTEXT_EVENTS|
- MONO_PROFILE_ASSEMBLY_EVENTS|MONO_PROFILE_GC_FINALIZATION;
-
- max_allocated_sample_hits = mono_cpu_count () * 1000;
-
- p = desc;
- if (strncmp (p, "log", 3))
- usage (1);
- p += 3;
- if (*p == ':')
- p++;
- for (; *p; p = opt) {
- char *val;
- if (*p == ',') {
- opt = p + 1;
- continue;
- }
- if ((opt = match_option (p, "help", NULL)) != p) {
- usage (0);
- continue;
- }
- if ((opt = match_option (p, "calls", NULL)) != p) {
- calls_enabled = 1;
- continue;
- }
- if ((opt = match_option (p, "nocalls", NULL)) != p) {
- events &= ~MONO_PROFILE_ENTER_LEAVE;
- nocalls = 1;
- continue;
- }
- if ((opt = match_option (p, "alloc", NULL)) != p) {
- allocs_enabled = 1;
- continue;
- }
- if ((opt = match_option (p, "noalloc", NULL)) != p) {
- events &= ~MONO_PROFILE_ALLOCATIONS;
- events &= ~MONO_PROFILE_GC_MOVES;
- continue;
- }
- if ((opt = match_option (p, "nocounters", NULL)) != p) {
- no_counters = TRUE;
- continue;
- }
- if ((opt = match_option (p, "time", &val)) != p) {
- // For backwards compatibility.
- if (strcmp (val, "fast") && strcmp (val, "null"))
- usage (1);
- g_free (val);
- continue;
- }
- if ((opt = match_option (p, "report", NULL)) != p) {
- do_report = 1;
- continue;
- }
- if ((opt = match_option (p, "debug", NULL)) != p) {
- do_debug = 1;
- continue;
- }
- if ((opt = match_option (p, "sampling-real", NULL)) != p) {
- sampling_mode = MONO_PROFILER_STAT_MODE_REAL;
- continue;
- }
- if ((opt = match_option (p, "sampling-process", NULL)) != p) {
- sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
- continue;
- }
- if ((opt = match_option (p, "heapshot", &val)) != p) {
- events &= ~MONO_PROFILE_ALLOCATIONS;
- events &= ~MONO_PROFILE_GC_MOVES;
- events &= ~MONO_PROFILE_ENTER_LEAVE;
- nocalls = 1;
- do_heap_shot = 1;
- set_hsmode (val, 1);
- continue;
- }
- if ((opt = match_option (p, "sample", &val)) != p) {
- events &= ~MONO_PROFILE_ALLOCATIONS;
- events &= ~MONO_PROFILE_GC_MOVES;
- events &= ~MONO_PROFILE_ENTER_LEAVE;
- nocalls = 1;
- set_sample_freq (val);
- continue;
- }
- if ((opt = match_option (p, "zip", NULL)) != p) {
- use_zip = 1;
- continue;
- }
- if ((opt = match_option (p, "output", &val)) != p) {
- filename = val;
- continue;
- }
- if ((opt = match_option (p, "port", &val)) != p) {
- char *end;
- command_port = strtoul (val, &end, 10);
- g_free (val);
- continue;
- }
- if ((opt = match_option (p, "maxframes", &val)) != p) {
- char *end;
- num_frames = strtoul (val, &end, 10);
- if (num_frames > MAX_FRAMES)
- num_frames = MAX_FRAMES;
- g_free (val);
- notraces = num_frames == 0;
- continue;
- }
- if ((opt = match_option (p, "maxsamples", &val)) != p) {
- char *end;
- max_allocated_sample_hits = strtoul (val, &end, 10);
- if (!max_allocated_sample_hits)
- max_allocated_sample_hits = G_MAXINT32;
- g_free (val);
- continue;
- }
- if ((opt = match_option (p, "calldepth", &val)) != p) {
- char *end;
- max_call_depth = strtoul (val, &end, 10);
- g_free (val);
- continue;
- }
- if ((opt = match_option (p, "counters", NULL)) != p) {
- // For backwards compatibility.
- continue;
- }
- if ((opt = match_option (p, "coverage", NULL)) != p) {
- do_coverage = 1;
- events |= MONO_PROFILE_ENTER_LEAVE;
- debug_coverage = g_hasenv ("MONO_PROFILER_DEBUG_COVERAGE");
- continue;
- }
- if ((opt = match_option (p, "onlycoverage", NULL)) != p) {
- only_coverage = TRUE;
- continue;
- }
- if ((opt = match_option (p, "covfilter-file", &val)) != p) {
- FILE *filter_file;
- char *line, *content;
-
- if (filters == NULL)
- filters = g_ptr_array_new ();
-
- filter_file = fopen (val, "r");
- if (filter_file == NULL) {
- fprintf (stderr, "Unable to open %s\n", val);
- exit (0);
- }
-
- /* Don't need to free content as it is referred to by the lines stored in @filters */
- content = get_file_content (filter_file);
- if (content == NULL)
- fprintf (stderr, "WARNING: %s is greater than 128kb - ignoring\n", val);
-
- while ((line = get_next_line (content, &content)))
- g_ptr_array_add (filters, g_strchug (g_strchomp (line)));
-
- fclose (filter_file);
- continue;
- }
- if ((opt = match_option (p, "covfilter", &val)) != p) {
- if (filters == NULL)
- filters = g_ptr_array_new ();
-
- g_ptr_array_add (filters, val);
- continue;
- }
- if (opt == p) {
- usage (0);
- exit (0);
- }
- }
-
- if (calls_enabled) {
- events |= MONO_PROFILE_ENTER_LEAVE;
- nocalls = 0;
- }
-
- if (allocs_enabled) {
- events |= MONO_PROFILE_ALLOCATIONS;
- events |= MONO_PROFILE_GC_MOVES;
- }
-
- // Only activate the bare minimum events the profiler needs to function.
- if (only_coverage) {
- if (!do_coverage) {
- fprintf (stderr, "The onlycoverage option is only valid when paired with the coverage option\n");
- exit (1);
- }
-
- no_counters = TRUE;
- events = MONO_PROFILE_GC | MONO_PROFILE_THREADS | MONO_PROFILE_ENTER_LEAVE | MONO_PROFILE_INS_COVERAGE;
- }
-
- init_time ();
-
- PROF_TLS_INIT ();
-
- prof = create_profiler (desc, filename, filters);
- if (!prof) {
- PROF_TLS_FREE ();
- return;
- }
-
- mono_lls_init (&profiler_thread_list, NULL);
-
- init_thread (prof, TRUE);
-
- mono_profiler_install (prof, log_shutdown);
- mono_profiler_install_gc (gc_event, gc_resize);
- mono_profiler_install_allocation (gc_alloc);
- mono_profiler_install_gc_moves (gc_moves);
- mono_profiler_install_gc_roots (gc_handle, gc_roots);
- mono_profiler_install_gc_finalize (finalize_begin, finalize_object_begin, finalize_object_end, finalize_end);
- mono_profiler_install_appdomain (NULL, domain_loaded, domain_unloaded, NULL);
- mono_profiler_install_appdomain_name (domain_name);
- mono_profiler_install_context (context_loaded, context_unloaded);
- mono_profiler_install_class (NULL, class_loaded, class_unloaded, NULL);
- mono_profiler_install_module (NULL, image_loaded, image_unloaded, NULL);
- mono_profiler_install_assembly (NULL, assembly_loaded, assembly_unloaded, NULL);
- mono_profiler_install_thread (thread_start, thread_end);
- mono_profiler_install_thread_name (thread_name);
- mono_profiler_install_enter_leave (method_enter, method_leave);
- mono_profiler_install_jit_end (method_jitted);
- mono_profiler_install_code_buffer_new (code_buffer_new);
- mono_profiler_install_exception (throw_exc, method_exc_leave, clause_exc);
- mono_profiler_install_monitor (monitor_event);
- mono_profiler_install_runtime_initialized (runtime_initialized);
- if (do_coverage)
- mono_profiler_install_coverage_filter (coverage_filter);
-
- if (do_mono_sample && sample_freq) {
- events |= MONO_PROFILE_STATISTICAL;
- mono_profiler_set_statistical_mode (sampling_mode, sample_freq);
- mono_profiler_install_statistical (mono_sample_hit);
- }
-
- mono_profiler_set_events ((MonoProfileFlags)events);
-}
+++ /dev/null
-#ifndef __MONO_PROFLOG_H__
-#define __MONO_PROFLOG_H__
-
-#define BUF_ID 0x4D504C01
-#define LOG_HEADER_ID 0x4D505A01
-#define LOG_VERSION_MAJOR 1
-#define LOG_VERSION_MINOR 1
-#define LOG_DATA_VERSION 13
-
-/*
- * Changes in major/minor versions:
- * version 1.0: removed sysid field from header
- * added args, arch, os fields to header
- *
- * Changes in data versions:
- * version 2: added offsets in heap walk
- * version 3: added GC roots
- * version 4: added sample/statistical profiling
- * version 5: added counters sampling
- * version 6: added optional backtrace in sampling info
- * version 8: added TYPE_RUNTIME and JIT helpers/trampolines
- * version 9: added MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING
- * version 10: added TYPE_COVERAGE
- * version 11: added thread ID to TYPE_SAMPLE_HIT
- added more load/unload events
- unload for class
- unload for image
- load/unload for appdomain
- load/unload for contexts
- load/unload/name for assemblies
- removed TYPE_LOAD_ERR flag (profiler never generated it, now removed from the format itself)
- added TYPE_GC_HANDLE_{CREATED,DESTROYED}_BT
- TYPE_JIT events are no longer guaranteed to have code start/size info (can be zero)
- * version 12: added MONO_COUNTER_PROFILER
- * version 13: added MONO_GC_EVENT_{PRE_STOP_WORLD_LOCKED,POST_START_WORLD_UNLOCKED}
- added TYPE_META + TYPE_SYNC_POINT
- removed il and native offset in TYPE_SAMPLE_HIT
- methods in backtraces are now encoded as proper method pointers
- removed flags in backtrace format
- removed flags in metadata events
- changed the following fields to a single byte rather than leb128
- TYPE_GC_EVENT: event_type, generation
- TYPE_HEAP_ROOT: root_type
- TYPE_JITHELPER: type
- TYPE_SAMPLE_HIT: sample_type
- TYPE_CLAUSE: clause_type
- TYPE_SAMPLE_COUNTERS_DESC: type, unit, variance
- TYPE_SAMPLE_COUNTERS: type
- added time fields to all events that were missing one
- TYPE_HEAP_OBJECT
- TYPE_HEAP_ROOT
- TYPE_SAMPLE_USYM
- TYPE_SAMPLE_COUNTERS_DESC
- TYPE_COVERAGE_METHOD
- TYPE_COVERAGE_STATEMENT
- TYPE_COVERAGE_CLASS
- TYPE_COVERAGE_ASSEMBLY
- moved the time field in TYPE_SAMPLE_HIT to right after the event byte, now encoded as a regular time field
- changed the time field in TYPE_SAMPLE_COUNTERS to be encoded as a regular time field (in nanoseconds)
- added TYPE_GC_FINALIZE_{START,END,OBJECT_START,OBJECT_END}
- */
-
-enum {
- TYPE_ALLOC,
- TYPE_GC,
- TYPE_METADATA,
- TYPE_METHOD,
- TYPE_EXCEPTION,
- TYPE_MONITOR,
- TYPE_HEAP,
- TYPE_SAMPLE,
- TYPE_RUNTIME,
- TYPE_COVERAGE,
- TYPE_META,
- /* extended type for TYPE_HEAP */
- TYPE_HEAP_START = 0 << 4,
- TYPE_HEAP_END = 1 << 4,
- TYPE_HEAP_OBJECT = 2 << 4,
- TYPE_HEAP_ROOT = 3 << 4,
- /* extended type for TYPE_METADATA */
- TYPE_END_LOAD = 2 << 4,
- TYPE_END_UNLOAD = 4 << 4,
- /* extended type for TYPE_GC */
- TYPE_GC_EVENT = 1 << 4,
- TYPE_GC_RESIZE = 2 << 4,
- TYPE_GC_MOVE = 3 << 4,
- TYPE_GC_HANDLE_CREATED = 4 << 4,
- TYPE_GC_HANDLE_DESTROYED = 5 << 4,
- TYPE_GC_HANDLE_CREATED_BT = 6 << 4,
- TYPE_GC_HANDLE_DESTROYED_BT = 7 << 4,
- TYPE_GC_FINALIZE_START = 8 << 4,
- TYPE_GC_FINALIZE_END = 9 << 4,
- TYPE_GC_FINALIZE_OBJECT_START = 10 << 4,
- TYPE_GC_FINALIZE_OBJECT_END = 11 << 4,
- /* extended type for TYPE_METHOD */
- TYPE_LEAVE = 1 << 4,
- TYPE_ENTER = 2 << 4,
- TYPE_EXC_LEAVE = 3 << 4,
- TYPE_JIT = 4 << 4,
- /* extended type for TYPE_EXCEPTION */
- TYPE_THROW_NO_BT = 0 << 7,
- TYPE_THROW_BT = 1 << 7,
- TYPE_CLAUSE = 1 << 4,
- /* extended type for TYPE_ALLOC */
- TYPE_ALLOC_NO_BT = 0 << 4,
- TYPE_ALLOC_BT = 1 << 4,
- /* extended type for TYPE_MONITOR */
- TYPE_MONITOR_NO_BT = 0 << 7,
- TYPE_MONITOR_BT = 1 << 7,
- /* extended type for TYPE_SAMPLE */
- TYPE_SAMPLE_HIT = 0 << 4,
- TYPE_SAMPLE_USYM = 1 << 4,
- TYPE_SAMPLE_UBIN = 2 << 4,
- TYPE_SAMPLE_COUNTERS_DESC = 3 << 4,
- TYPE_SAMPLE_COUNTERS = 4 << 4,
- /* extended type for TYPE_RUNTIME */
- TYPE_JITHELPER = 1 << 4,
- /* extended type for TYPE_COVERAGE */
- TYPE_COVERAGE_ASSEMBLY = 0 << 4,
- TYPE_COVERAGE_METHOD = 1 << 4,
- TYPE_COVERAGE_STATEMENT = 2 << 4,
- TYPE_COVERAGE_CLASS = 3 << 4,
- /* extended type for TYPE_META */
- TYPE_SYNC_POINT = 0 << 4,
- TYPE_END
-};
-
-enum {
- /* metadata type byte for TYPE_METADATA */
- TYPE_CLASS = 1,
- TYPE_IMAGE = 2,
- TYPE_ASSEMBLY = 3,
- TYPE_DOMAIN = 4,
- TYPE_THREAD = 5,
- TYPE_CONTEXT = 6,
-};
-
-typedef enum {
- SYNC_POINT_PERIODIC,
- SYNC_POINT_WORLD_STOP,
- SYNC_POINT_WORLD_START
-} MonoProfilerSyncPointType;
-
-// Sampling sources
-// Unless you have compiled with --enable-perf-events, only SAMPLE_CYCLES is available
-enum {
- SAMPLE_CYCLES = 1,
- SAMPLE_INSTRUCTIONS,
- SAMPLE_CACHE_MISSES,
- SAMPLE_CACHE_REFS,
- SAMPLE_BRANCHES,
- SAMPLE_BRANCH_MISSES,
- SAMPLE_LAST
-};
-
-#endif /* __MONO_PROFLOG_H__ */
+++ /dev/null
-/*
- * mono-codeanalyst.c: VTune profiler
- *
- * Author:
- * Virgile Bello (virgile.bello@gmail.com)
- *
- * (C) 2011 Virgile Bello
- *
- * 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.
- */
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/debug-internals.h>
-#include <string.h>
-#include <glib.h>
-
-#define bool char
-
-#include <jitprofiling.h>
-
-static const char*
-code_buffer_desc (MonoProfilerCodeBufferType type)
-{
- switch (type) {
- case MONO_PROFILER_CODE_BUFFER_METHOD:
- return "code_buffer_method";
- case MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE:
- return "code_buffer_method_trampoline";
- case MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE:
- return "code_buffer_unbox_trampoline";
- case MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE:
- return "code_buffer_imt_trampoline";
- case MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE:
- return "code_buffer_generics_trampoline";
- case MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE:
- return "code_buffer_specific_trampoline";
- case MONO_PROFILER_CODE_BUFFER_HELPER:
- return "code_buffer_misc_helper";
- case MONO_PROFILER_CODE_BUFFER_MONITOR:
- return "code_buffer_monitor";
- case MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE:
- return "code_buffer_delegate_invoke";
- case MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING:
- return "code_buffer_exception_handling";
- default:
- return "unspecified";
- }
-}
-
-/* called at the end of the program */
-static void
-codeanalyst_shutdown (MonoProfiler *prof)
-{
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL);
-}
-
-static void
-method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
- if (result == MONO_PROFILE_OK) {
- int i;
- MonoDebugSourceLocation *sourceLoc;
- MonoDebugMethodJitInfo *dmji;
- MonoClass *klass = mono_method_get_class (method);
- char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
- char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
- char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
- gpointer code_start = mono_jit_info_get_code_start (jinfo);
- int code_size = mono_jit_info_get_code_size (jinfo);
-
- iJIT_Method_Load vtuneMethod;
- memset(&vtuneMethod, 0, sizeof(vtuneMethod));
- vtuneMethod.method_id = iJIT_GetNewMethodID();
- vtuneMethod.method_name = name;
- vtuneMethod.method_load_address = code_start;
- vtuneMethod.method_size = code_size;
- vtuneMethod.class_file_name = classname;
-
- dmji = mono_debug_find_method (method, mono_domain_get());
-
- if (dmji != NULL)
- {
- vtuneMethod.line_number_size = dmji->num_line_numbers;
- vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
- (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
-
- for (i = 0; i < dmji->num_line_numbers; ++i)
- {
- sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
- if (sourceLoc == NULL)
- {
- g_free (vtuneMethod.line_number_table);
- vtuneMethod.line_number_table = NULL;
- vtuneMethod.line_number_size = 0;
- break;
- }
- if (i == 0)
- vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
- vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
- vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
- mono_debug_free_source_location (sourceLoc);
- }
- mono_debug_free_method_jit_info (dmji);
- }
-
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
-
- if (vtuneMethod.source_file_name != NULL)
- g_free (vtuneMethod.source_file_name);
- if (vtuneMethod.line_number_table != NULL)
- g_free (vtuneMethod.line_number_table);
-
- g_free (signature);
- g_free (name);
- g_free (classname);
- }
-}
-
-static void
-code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
-{
- char *name;
- iJIT_Method_Load vtuneMethod;
-
- if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE)
- name = g_strdup_printf ("code_buffer_specific_trampoline_%s", (char*) data);
- else
- name = (char*) code_buffer_desc (type);
-
- memset (&vtuneMethod, 0, sizeof (vtuneMethod));
- vtuneMethod.method_id = iJIT_GetNewMethodID ();
- vtuneMethod.method_name = name;
- vtuneMethod.method_load_address = buffer;
- vtuneMethod.method_size = size;
-
- iJIT_NotifyEvent (iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
-
- if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
- g_free (name);
- }
-}
-
-/* the entry point */
-void
-mono_profiler_startup (const char *desc)
-{
- iJIT_IsProfilingActiveFlags flags = iJIT_IsProfilingActive();
- if (flags == iJIT_SAMPLING_ON)
- {
- mono_profiler_install (NULL, codeanalyst_shutdown);
- mono_profiler_install_jit_end (method_jit_result);
- mono_profiler_install_code_buffer_new (code_buffer_new);
- mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
- }
-}
* - column: The column on the line
*/
#include <config.h>
-#include "mono-profiler-log.h"
+#include "log.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>
#define HASH_SIZE 9371
#define SMALL_HASH_SIZE 31
-#if defined(__native_client__) || defined(__native_client_codegen__)
-volatile int __nacl_thread_suspension_needed = 0;
-void __nacl_suspend_thread_if_needed() {}
-#endif
-
static int debug = 0;
static int collect_traces = 0;
static int show_traces = 0;
append_path ("PATH", $profbuilddir);
# first a basic test
-$report = run_test ("test-alloc.exe");
+$report = run_test ("test-alloc.exe", "report,legacy,calls,alloc");
check_report_basics ($report);
check_report_calls ($report, "T:Main (string[])" => 1);
check_report_allocation ($report, "System.Object" => 1000000);
report_errors ();
# test additional named threads and method calls
-$report = run_test ("test-busy.exe");
+$report = run_test ("test-busy.exe", "report,legacy,calls,alloc");
check_report_basics ($report);
check_report_calls ($report, "T:Main (string[])" => 1);
check_report_threads ($report, "BusyHelper");
check_report_calls ($report, "T:test ()" => 10, "T:test3 ()" => 10, "T:test2 ()" => 1);
report_errors ();
# test with the sampling profiler
-$report = run_test ("test-busy.exe", "report,sample");
+$report = run_test ("test-busy.exe", "report,legacy,sample");
check_report_basics ($report);
check_report_threads ($report, "BusyHelper");
# at least 40% of the samples should hit each of the two busy methods
#check_report_samples ($report, "T:test ()" => 40, "T:test3 ()" => 40);
report_errors ();
# test lock events
-$report = run_test ("test-monitor.exe");
+$report = run_test ("test-monitor.exe", "report,legacy,calls,alloc");
check_report_basics ($report);
check_report_calls ($report, "T:Main (string[])" => 1);
# we hope for at least some contention, this is not entirely reliable
check_report_locks ($report, 1, 1);
report_errors ();
# test exceptions
-$report = run_test ("test-excleave.exe");
+$report = run_test ("test-excleave.exe", "report,legacy,calls");
check_report_basics ($report);
check_report_calls ($report, "T:Main (string[])" => 1, "T:throw_ex ()" => 1000);
check_report_exceptions ($report, 1000, 1000, 1000);
report_errors ();
# test heapshot
-$report = run_test_sgen ("test-heapshot.exe", "report,heapshot");
+$report = run_test_sgen ("test-heapshot.exe", "report,heapshot,legacy");
if ($report ne "missing binary") {
check_report_basics ($report);
check_report_heapshot ($report, 0, {"T" => 5000});
report_errors ();
}
# test heapshot traces
-$report = run_test_sgen ("test-heapshot.exe", "heapshot,output=-traces.mlpd", "--traces traces.mlpd");
+$report = run_test_sgen ("test-heapshot.exe", "heapshot,output=-traces.mlpd,legacy", "--traces traces.mlpd");
if ($report ne "missing binary") {
check_report_basics ($report);
check_report_heapshot ($report, 0, {"T" => 5000});
report_errors ();
}
# test traces
-$report = run_test ("test-traces.exe", "output=-traces.mlpd", "--traces traces.mlpd");
+$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=-traces.mlpd", "--traces traces.mlpd");
check_report_basics ($report);
check_call_traces ($report,
"T:level3 (int)" => [2020, "T:Main (string[])"],
);
report_errors ();
# test traces without enter/leave events
-$report = run_test ("test-traces.exe", "nocalls,output=-traces.mlpd", "--traces traces.mlpd");
+$report = run_test ("test-traces.exe", "legacy,alloc,output=-traces.mlpd", "--traces traces.mlpd");
check_report_basics ($report);
# this has been broken recently
check_exception_traces ($report,
--- /dev/null
+/*
+ * mono-codeanalyst.c: VTune profiler
+ *
+ * Author:
+ * Virgile Bello (virgile.bello@gmail.com)
+ *
+ * (C) 2011 Virgile Bello
+ *
+ * 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.
+ */
+#include <mono/metadata/profiler.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/debug-internals.h>
+#include <string.h>
+#include <glib.h>
+
+#define bool char
+
+#include <jitprofiling.h>
+
+static const char*
+code_buffer_desc (MonoProfilerCodeBufferType type)
+{
+ switch (type) {
+ case MONO_PROFILER_CODE_BUFFER_METHOD:
+ return "code_buffer_method";
+ case MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE:
+ return "code_buffer_method_trampoline";
+ case MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE:
+ return "code_buffer_unbox_trampoline";
+ case MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE:
+ return "code_buffer_imt_trampoline";
+ case MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE:
+ return "code_buffer_generics_trampoline";
+ case MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE:
+ return "code_buffer_specific_trampoline";
+ case MONO_PROFILER_CODE_BUFFER_HELPER:
+ return "code_buffer_misc_helper";
+ case MONO_PROFILER_CODE_BUFFER_MONITOR:
+ return "code_buffer_monitor";
+ case MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE:
+ return "code_buffer_delegate_invoke";
+ case MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING:
+ return "code_buffer_exception_handling";
+ default:
+ return "unspecified";
+ }
+}
+
+/* called at the end of the program */
+static void
+codeanalyst_shutdown (MonoProfiler *prof)
+{
+ iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL);
+}
+
+static void
+method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
+ if (result == MONO_PROFILE_OK) {
+ int i;
+ MonoDebugSourceLocation *sourceLoc;
+ MonoDebugMethodJitInfo *dmji;
+ MonoClass *klass = mono_method_get_class (method);
+ char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
+ char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
+ char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
+ gpointer code_start = mono_jit_info_get_code_start (jinfo);
+ int code_size = mono_jit_info_get_code_size (jinfo);
+
+ iJIT_Method_Load vtuneMethod;
+ memset(&vtuneMethod, 0, sizeof(vtuneMethod));
+ vtuneMethod.method_id = iJIT_GetNewMethodID();
+ vtuneMethod.method_name = name;
+ vtuneMethod.method_load_address = code_start;
+ vtuneMethod.method_size = code_size;
+ vtuneMethod.class_file_name = classname;
+
+ dmji = mono_debug_find_method (method, mono_domain_get());
+
+ if (dmji != NULL)
+ {
+ vtuneMethod.line_number_size = dmji->num_line_numbers;
+ vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
+ (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
+
+ for (i = 0; i < dmji->num_line_numbers; ++i)
+ {
+ sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
+ if (sourceLoc == NULL)
+ {
+ g_free (vtuneMethod.line_number_table);
+ vtuneMethod.line_number_table = NULL;
+ vtuneMethod.line_number_size = 0;
+ break;
+ }
+ if (i == 0)
+ vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
+ vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
+ vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
+ mono_debug_free_source_location (sourceLoc);
+ }
+ mono_debug_free_method_jit_info (dmji);
+ }
+
+ iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
+
+ if (vtuneMethod.source_file_name != NULL)
+ g_free (vtuneMethod.source_file_name);
+ if (vtuneMethod.line_number_table != NULL)
+ g_free (vtuneMethod.line_number_table);
+
+ g_free (signature);
+ g_free (name);
+ g_free (classname);
+ }
+}
+
+static void
+code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
+{
+ char *name;
+ iJIT_Method_Load vtuneMethod;
+
+ if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE)
+ name = g_strdup_printf ("code_buffer_specific_trampoline_%s", (char*) data);
+ else
+ name = (char*) code_buffer_desc (type);
+
+ memset (&vtuneMethod, 0, sizeof (vtuneMethod));
+ vtuneMethod.method_id = iJIT_GetNewMethodID ();
+ vtuneMethod.method_name = name;
+ vtuneMethod.method_load_address = buffer;
+ vtuneMethod.method_size = size;
+
+ iJIT_NotifyEvent (iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
+
+ if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
+ g_free (name);
+ }
+}
+
+/* the entry point */
+void
+mono_profiler_startup (const char *desc)
+{
+ iJIT_IsProfilingActiveFlags flags = iJIT_IsProfilingActive();
+ if (flags == iJIT_SAMPLING_ON)
+ {
+ mono_profiler_install (NULL, codeanalyst_shutdown);
+ mono_profiler_install_jit_end (method_jit_result);
+ mono_profiler_install_code_buffer_new (code_buffer_new);
+ mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+ }
+}
#define SGEN_PAUSE_MODE_MAX_PAUSE_MARGIN 0.5f
+/*
+ * In practice, for nurseries smaller than this, the parallel minor tends to be
+ * ineffective, even leading to regressions. Avoid using it for smaller nurseries.
+ */
+#define SGEN_PARALLEL_MINOR_MIN_NURSERY_SIZE (1 << 24)
+
#endif
object_ops_nopar = &sgen_minor_collector.serial_ops_with_concurrent_major;
} else {
object_ops_nopar = &sgen_minor_collector.serial_ops;
- if (sgen_minor_collector.is_parallel) {
+ if (sgen_minor_collector.is_parallel && sgen_nursery_size >= SGEN_PARALLEL_MINOR_MIN_NURSERY_SIZE) {
object_ops_par = &sgen_minor_collector.parallel_ops;
is_parallel = TRUE;
}
if (major_collector.is_concurrent || sgen_minor_collector.is_parallel) {
int num_workers = 1;
if (major_collector.is_parallel || sgen_minor_collector.is_parallel) {
- /* FIXME Detect the number of physical cores, instead of logical */
- num_workers = mono_cpu_count () / 2;
- if (num_workers < 1)
+ num_workers = mono_cpu_count ();
+ if (num_workers <= 1) {
num_workers = 1;
+ major_collector.is_parallel = FALSE;
+ sgen_minor_collector.is_parallel = FALSE;
+ }
}
- sgen_workers_init (num_workers, (SgenWorkerCallback) major_collector.worker_init_cb);
+ if (major_collector.is_concurrent || sgen_minor_collector.is_parallel)
+ sgen_workers_init (num_workers, (SgenWorkerCallback) major_collector.worker_init_cb);
}
sgen_memgov_init (max_heap, soft_limit, debug_print_allowance, allowance_ratio, save_target);
WorkerData *data = (WorkerData*)data_untyped;
int current_worker = (int) (data - workers_data);
- return started && current_worker < active_workers_num;
+ return started && current_worker < active_workers_num && state_is_working_or_enqueued (data->state);
}
static void
sgen-bridge-xref.exe
endif
-if NACL_CODEGEN
-# Tests that use Thread.Abort()
-PLATFORM_DISABLED_TESTS= abort-stress-1.exe \
- abort-stress-2.exe \
- abort-stress-3.exe \
- appdomain-thread-abort.exe \
- async-exc-compilation.exe \
- bug-561239.exe \
- bug-70561.exe \
- finalizer-abort.exe \
- finally_guard.exe \
- finally_block_ending_in_dead_bb.exe \
- main-returns-abort-resetabort.exe \
- main-returns-background-abort-resetabort.exe \
- thread6.exe \
- threadpool-exceptions5.exe \
- threadpool-exceptions6.exe
-
-PLATFORM_DISABLED_TESTS+= w32message.exe
-
-# Tests that rely on AppDomain.Unload
-PLATFORM_DISABLED_TESTS+= appdomain-async-invoke.exe \
- appdomain-exit.exe \
- appdomain-unload-callback.exe \
- appdomain-unload.exe \
- domain-stress.exe \
- generic-unloading.2.exe \
- monitor.exe \
- remoting4.exe \
- threadpool-exceptions7.exe \
- xdomain-threads.exe
-
-# pinvoke2 attaches a thread to the runtime, but
-# doesn't 'unattach' it and it hangs in GC on exit
-PLATFORM_DISABLED_TESTS+= pinvoke2.exe
-
-# Tests that currently hang waiting for non-main threads
-# to exit in NaCl, need to investigate. Most are AppDomain
-# creation and Delegate tests.
-PLATFORM_DISABLED_TESTS+= appdomain1.exe \
- delegate9.exe \
- marshal-valuetypes.exe \
- cross-domain.exe \
- stackframes-async.2.exe \
- generic-marshalbyref.2.exe \
- generic-xdomain.2.exe \
- bug-415577.exe
-
-# Tests that fail trying to write files (appdomain create mostly)
-PLATFORM_DISABLED_TESTS+= bug-335131.2.exe \
- bug-349190.2.exe \
- bug-80307.exe \
- bug-462592.exe
-
-# FIXME: don't know why delegate2.exe fails, it shouldn't
-PLATFORM_DISABLED_TESTS+= delegate2.exe
-
-# These tests newly fail with the latest revision. pinvoke3 fails because
-# of a thread attach, the others have not been investigated. TODO revisit.
-PLATFORM_DISABLED_TESTS+= pinvoke3.exe \
- async_read.exe \
- async-with-cb-throws.exe \
- appdomain-unload-doesnot-raise-pending-events.exe \
- gsharing-valuetype-layout.exe
-
-if X86
-# FIXME: There are problems with async callbacks and results on NaCl 32-bit
-PLATFORM_DISABLED_TESTS+= delegate1.exe \
- delegate3.exe \
- delegate5.exe \
- delegate8.exe \
- threadpool.exe \
- threadpool1.exe \
- threadpool-exceptions3.exe \
- bug-323114.exe \
- delegate-exit.exe \
- bug-80392.2.exe
-
-# FIXME: These tests hang/fail for unknown reasons, deal with exiting
-PLATFORM_DISABLED_TESTS+= main-returns-background-resetabort.exe \
- main-returns-background.exe \
- main-returns-background-change.exe
-endif
-
-endif
-
if ENABLE_COOP
COOP_DISABLED_TESTS= thunks.exe
else
# delegate-invoke.exe depends on 929c6bc9b6d76a273f251e6f5dfacac36e9c38bd which was
# reverted.
# bug-Xamarin-5278.exe got broken by 5d26590e79da139a284459299aee95c25f4cd835
-# bug-45841-fpstack-exceptions.exe: https://bugzilla.xamarin.com/show_bug.cgi?id=47053
# appdomain-thread-abort.exe: https://bugzilla.xamarin.com/show_bug.cgi?id=47054
KNOWN_FAILING_TESTS = \
delegate-async-exception.exe \
bug-459094.exe \
delegate-invoke.exe \
bug-Xamarin-5278.exe \
- bug-45841-fpstack-exceptions.exe \
appdomain-thread-abort.exe
DISABLED_TESTS = \
bug-327438.2.exe \
bug-335131.2.exe \
bug-415577.exe \
+ bug-45841-fpstack-exceptions.exe \
bug-461867.exe \
bug-461941.exe \
bug-46661.exe \
#
# Test that no symbols are missed in eglib-remap.h
#
-if NACL_CODEGEN
-else
if PLATFORM_LINUX
test-platform: test-eglib-remap
else
test-platform: test-eglib-remap
endif
endif
-endif
# The following regexp describes all symbols that start with "g_" but are not part of eglibc.
# The optional underscore prepending symbol names may or may not appear depending on the
# system and the state of the leading-underscore compiler flag.
test-generic-sharing-managed: test-runner.exe $(TESTS_GSHARED) $(TESTSAOT_GSHARED)
$(Q) $(TOOLS_RUNTIME) $(TEST_RUNNER) -j a --testsuite-name "gshared" --disabled "$(DISABLED_TESTS)" --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(TESTS_GSHARED)
-if NACL_CODEGEN
-test-generic-sharing:
-else
test-generic-sharing:
@if test x$(M) != x0; then $(MAKE) test-generic-sharing-managed; else $(MAKE) test-generic-sharing-normal; fi
-endif
EXTRA_DIST += async-exceptions.cs
async-exceptions.exe : async-exceptions.cs
touch libtest.c
-if NACL_CODEGEN
-test-process-exit:
-else
EXTRA_DIST += threadpool-in-processexit.cs threadpool-in-processexit.exe.stdout.expected
test-process-exit:
@$(MCS) $(srcdir)/threadpool-in-processexit.cs -out:threadpool-in-processexit.exe
@echo "Testing threadpool-in-processexit.exe..."
@$(RUNTIME) threadpool-in-processexit.exe > threadpool-in-processexit.exe.stdout
@diff -w threadpool-in-processexit.exe.stdout $(srcdir)/threadpool-in-processexit.exe.stdout.expected
-endif
# tests that expect a 1 exit code
TESTS_UNHANDLED_EXCEPTION_1_SRC = \
.locals init (valuetype [System.Data]System.Data.SqlTypes.SqlDecimal V_0)
.try
{
- ldc.r8 5
+ ldstr "Exception 1"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
pop
IL_0021: nop
.try
{
- ldc.r8 5
+ ldstr "Exception 2"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
pop
IL_0033: nop
.try
{
- ldc.r8 5
+ ldstr "Exception 3"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
IL_0044: leave.s IL_0049
IL_0049: nop
.try
{
- ldc.r8 5
+ ldstr "Exception 4"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
pop
IL_005f: nop
.try
{
- ldc.r8 5
+ ldstr "Exception 5"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
pop
IL_0071: nop
.try
{
- ldc.r8 5
+ ldstr "Exception 6"
newobj instance void [mscorlib]System.OverflowException::.ctor(string)
throw
pop
#endif /* HAVE_MORECORE */
#endif /* DARWIN */
-#if defined(__native_client__)
-#undef HAVE_MMAP
-#undef HAVE_MREMAP
-#define HAVE_MMAP 0
-#define HAVE_MREMAP 0
-#endif
-
#ifndef LACKS_SYS_TYPES_H
#include <sys/types.h> /* For size_t */
#endif /* LACKS_SYS_TYPES_H */
void
mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
{
-#if defined (__native_client__) || defined (HOST_WATCHOS)
+#if defined (HOST_WATCHOS)
printf("WARNING: mono_arch_sigctx_to_monoctx() called!\n");
mctx->eax = 0xDEADBEEF;
mctx->ebx = 0xDEADBEEF;
mctx->esi = ctx->SC_ESI;
mctx->edi = ctx->SC_EDI;
mctx->eip = ctx->SC_EIP;
-#endif /* if defined(__native_client__) */
+#endif
}
void
mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
{
-#if defined(__native_client__) || defined(HOST_WATCHOS)
+#if defined(HOST_WATCHOS)
printf("WARNING: mono_arch_monoctx_to_sigctx() called!\n");
#elif MONO_CROSS_COMPILE
g_assert_not_reached ();
ctx->SC_ESI = mctx->esi;
ctx->SC_EDI = mctx->edi;
ctx->SC_EIP = mctx->eip;
-#endif /* __native_client__ */
+#endif
}
#elif (defined(__x86_64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_AMD64)) /* defined(__i386__) */
void
mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
{
-#if defined(__native_client_codegen__) || defined(__native_client__)
- printf("WARNING: mono_arch_sigctx_to_monoctx() called!\n");
-#endif
-
#ifdef MONO_CROSS_COMPILE
g_assert_not_reached ();
#elif defined(MONO_SIGNAL_USE_UCONTEXT_T)
void
mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
{
-#if defined(__native_client__) || defined(__native_client_codegen__)
- printf("WARNING: mono_arch_monoctx_to_sigctx() called!\n");
-#endif
-
#ifdef MONO_CROSS_COMPILE
g_assert_not_reached ();
#elif defined(MONO_SIGNAL_USE_UCONTEXT_T)
{
#ifdef MONO_CROSS_COMPILE
g_assert_not_reached ();
-#elif defined(__native_client__)
- g_assert_not_reached ();
#else
arm_ucontext *my_uc = sigctx;
{
#ifdef MONO_CROSS_COMPILE
g_assert_not_reached ();
-#elif defined(__native_client__)
- g_assert_not_reached ();
#else
arm_ucontext *my_uc = ctx;
#endif
#endif
-#if defined(__native_client__)
-#undef MONO_SIGNAL_USE_UCONTEXT_T
-#endif
-
#ifdef __HAIKU__
/* sigcontext surrogate */
struct sigcontext {
#include <mono/arch/amd64/amd64-codegen.h>
-#if !defined( HOST_WIN32 ) && !defined(__native_client__) && !defined(__native_client_codegen__)
+#if !defined( HOST_WIN32 )
#if defined(HAVE_SIGACTION) || defined(__APPLE__) // the __APPLE__ check is required for the tvos simulator, which has ucontext_t but not sigaction
#define MONO_SIGNAL_USE_UCONTEXT_T 1
extern void mono_context_get_current (void *);
#define MONO_CONTEXT_GET_CURRENT(ctx) do { mono_context_get_current((void*)&(ctx)); } while (0)
-#elif defined(__native_client__)
-#define MONO_CONTEXT_GET_CURRENT(ctx) \
- __asm__ __volatile__( \
- "movq $0x0, %%nacl:0x00(%%r15, %0, 1)\n" \
- "movq %%rcx, %%nacl:0x08(%%r15, %0, 1)\n" \
- "movq %%rdx, %%nacl:0x10(%%r15, %0, 1)\n" \
- "movq %%rbx, %%nacl:0x18(%%r15, %0, 1)\n" \
- "movq %%rsp, %%nacl:0x20(%%r15, %0, 1)\n" \
- "movq %%rbp, %%nacl:0x28(%%r15, %0, 1)\n" \
- "movq %%rsi, %%nacl:0x30(%%r15, %0, 1)\n" \
- "movq %%rdi, %%nacl:0x38(%%r15, %0, 1)\n" \
- "movq %%r8, %%nacl:0x40(%%r15, %0, 1)\n" \
- "movq %%r9, %%nacl:0x48(%%r15, %0, 1)\n" \
- "movq %%r10, %%nacl:0x50(%%r15, %0, 1)\n" \
- "movq %%r11, %%nacl:0x58(%%r15, %0, 1)\n" \
- "movq %%r12, %%nacl:0x60(%%r15, %0, 1)\n" \
- "movq %%r13, %%nacl:0x68(%%r15, %0, 1)\n" \
- "movq %%r14, %%nacl:0x70(%%r15, %0, 1)\n" \
- "movq %%r15, %%nacl:0x78(%%r15, %0, 1)\n" \
- "leaq (%%rip), %%rdx\n" \
- "movq %%rdx, %%nacl:0x80(%%r15, %0, 1)\n" \
- : \
- : "a" ((int64_t)&(ctx)) \
- : "rdx", "memory")
#else
#define MONO_CONTEXT_GET_CURRENT_GREGS(ctx) \
#define MONO_SOLIB_EXT ".dll"
#elif defined(__ppc__) && defined(TARGET_MACH)
#define MONO_SOLIB_EXT ".dylib"
-#elif defined(TARGET_MACH) && defined(TARGET_X86) && !defined(__native_client_codegen__)
+#elif defined(TARGET_MACH) && defined(TARGET_X86)
#define MONO_SOLIB_EXT ".dylib"
-#elif defined(TARGET_MACH) && defined(TARGET_AMD64) && !defined(__native_client_codegen__)
+#elif defined(TARGET_MACH) && defined(TARGET_AMD64)
#define MONO_SOLIB_EXT ".dylib"
#else
#define MONO_SOLIB_EXT ".so"
* \p length must be a multiple of the page size.
* \returns \c 0 on success.
*/
-#if defined(__native_client__)
-int
-mono_mprotect (void *addr, size_t length, int flags)
-{
- int prot = prot_from_flags (flags);
- void *new_addr;
-
- if (flags & MONO_MMAP_DISCARD) memset (addr, 0, length);
-
- new_addr = mmap(addr, length, prot, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
- if (new_addr == addr) return 0;
- return -1;
-}
-#else
int
mono_mprotect (void *addr, size_t length, int flags)
{
}
return mprotect (addr, length, prot);
}
-#endif // __native_client__
#else
#ifdef HOST_WIN32
// Windows specific implementation in mono-rand-windows.c
-#elif defined (HAVE_SYS_UN_H) && !defined(__native_client__)
+#elif defined (HAVE_SYS_UN_H)
#include <errno.h>
#include <fcntl.h>
#endif
}
-#ifndef __native_client__
-
static int suspend_signal_num = -1;
static int restart_signal_num = -1;
static int abort_signal_num = -1;
return abort_signal_num;
}
-#else
-
-void
-mono_threads_suspend_init_signals (void)
-{
- g_assert_not_reached ();
-}
-
-gint
-mono_threads_suspend_get_suspend_signal (void)
-{
- return -1;
-}
-
-gint
-mono_threads_suspend_get_restart_signal (void)
-{
- return -1;
-}
-
-gint
-mono_threads_suspend_get_abort_signal (void)
-{
- return -1;
-}
-
-#endif /* __native_client__ */
-
-
#endif /* defined(USE_POSIX_BACKEND) */
extern int tkill (pid_t tid, int signal);
#endif
-#if defined(_POSIX_VERSION) || defined(__native_client__)
+#if defined(_POSIX_VERSION)
#include <pthread.h>
errno = old_errno;
}
return result;
-#elif defined(__native_client__)
- /* Workaround pthread_kill abort() in NaCl glibc. */
- return 0;
#elif !defined(HAVE_PTHREAD_KILL)
g_error ("pthread_kill() is not supported by this platform");
#else
return !pthread_join (tid, &res);
}
-#endif /* defined(_POSIX_VERSION) || defined(__native_client__) */
+#endif /* defined(_POSIX_VERSION) */
#if defined(USE_POSIX_BACKEND)
((MonoThreadInfo*)info)->tls [key] = value;
}
-#if defined(__native_client__)
-void nacl_shutdown_gc_thread(void);
-#endif
-
/*
* mono_thread_info_exit:
*
void
mono_thread_info_exit (gsize exit_code)
{
-#if defined(__native_client__)
- nacl_shutdown_gc_thread();
-#endif
-
mono_thread_info_detach ();
mono_threads_platform_exit (0);
/* If this is defined, use the signals backed on Mach. Debug only as signals can't be made usable on OSX. */
// #define USE_SIGNALS_ON_MACH
-#if defined (_POSIX_VERSION) || defined (__native_client__)
+#if defined (_POSIX_VERSION)
#if defined (__MACH__) && !defined (USE_SIGNALS_ON_MACH)
#define USE_MACH_BACKEND
#else
#define USE_WINDOWS_BACKEND
#else
#error "no backend support for current platform"
-#endif /* defined (_POSIX_VERSION) || defined (__native_client__) */
+#endif /* defined (_POSIX_VERSION) */
enum {
STATE_STARTING = 0x00,
if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
return -1;
-#if defined(__native_client__) && (defined(__i386__) || defined(__x86_64))
-#define USE_X86_32BIT_INSTRUCTIONS 1
-#endif
-
-#if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
+#if (defined(__i386__) && defined(__GNUC__))
{
int r;
/* This depends on mask != 0 */
my_g_bit_nth_lsf_nomask (gsize mask)
{
/* Mask is expected to be != 0 */
-#if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
+#if (defined(__i386__) && defined(__GNUC__))
int r;
__asm__("bsfl %1,%0\n\t"
-<?xml version="1.0" encoding="utf-8"?>\r
+<?xml version="1.0" encoding="utf-8"?>\r
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
<ItemGroup Label="ProjectConfigurations">\r
<ProjectConfiguration Include="Debug|Win32">\r
<ClCompile Include="..\mono\metadata\mono-conc-hash.c" />\r
<ClCompile Include="..\mono\metadata\mono-mlist.c" />\r
<ClCompile Include="..\mono\metadata\mono-perfcounters.c" />\r
- <ClCompile Include="..\mono\metadata\nacl-stub.c" />\r
<ClCompile Include="..\mono\metadata\null-gc.c" />\r
<ClCompile Include="..\mono\metadata\number-ms.c" />\r
<ClCompile Include="..\mono\metadata\object.c" />\r
-<?xml version="1.0" encoding="utf-8"?>\r
+<?xml version="1.0" encoding="utf-8"?>\r
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
<ItemGroup>\r
<ClCompile Include="..\mono\metadata\assembly.c">\r
<ClCompile Include="..\mono\metadata\mono-security.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\nacl-stub.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\mono\metadata\null-gc.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
+++ /dev/null
-Building NaCl Mono with glibc (newlib support is eliminated but should still be buildable with small effort) is complex. Instructions live here for the adventurous: https://docs.google.com/a/google.com/document/d/1Jd_4M7mlmxF8daVbepAy_8RKYcRbhifXanRYyBKkVa4/pub
-
+++ /dev/null
-# Copyright (c) 2011 The Native Client Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that be
-# found in the LICENSE file.
-#
-
-set -o nounset
-set -o errexit
-
-# scripts that source this file must be run from within packages tree
-readonly SAVE_PWD=$(pwd)
-
-# Pick platform directory for compiler.
-readonly OS_NAME=$(uname -s)
-if [ $OS_NAME = "Darwin" ]; then
- readonly OS_SUBDIR="mac"
- readonly OS_SUBDIR_SHORT="mac"
-elif [ $OS_NAME = "Linux" ]; then
- readonly OS_SUBDIR="linux"
- readonly OS_SUBDIR_SHORT="linux"
-else
- readonly OS_SUBDIR="windows"
- readonly OS_SUBDIR_SHORT="win"
-fi
-
-readonly MACHINE=$(uname -m)
-if [ $MACHINE = "x86_64" ]; then
- readonly TARGET_BITSIZE=${TARGET_BITSIZE:-"64"}
- readonly HOST_BITSIZE=${HOST_BITSIZE:-"64"}
-else
- # uname -m reports i686 on Linux and i386 on Mac
- readonly TARGET_BITSIZE=${TARGET_BITSIZE:-"32"}
- readonly HOST_BITSIZE=${HOST_BITSIZE:-"32"}
-fi
-
-if [ $TARGET_BITSIZE == "64" ]; then
- readonly TARGET_BIT_PREFIX="64"
- readonly CROSS_ID=x86_64
-else
- readonly TARGET_BIT_PREFIX=""
- readonly CROSS_ID=i686
-fi
-# we might want to override the detected host platform (e.g. on OSX 10.6)
-if [ $HOST_BITSIZE == "64" ]; then
- readonly HOST_BIT_PREFIX="64"
-else
- readonly HOST_BIT_PREFIX=""
-fi
-
-export NACL_CROSS_PREFIX=${CROSS_ID}-nacl
-export NACL_CROSS_PREFIX_DASH=${NACL_CROSS_PREFIX}-
-
-readonly NACL_NEWLIB=${NACL_NEWLIB:-"0"}
-
-if [ $NACL_NEWLIB = "1" ]; then
- readonly NACL_SDK_BASE=${NACL_SDK_ROOT}/toolchain/${OS_SUBDIR_SHORT}_x86_newlib
-else
-case "${NACL_SDK_ROOT}" in
-*pepper_15* | *pepper_16* | *pepper_17*)
- readonly NACL_SDK_BASE=${NACL_SDK_ROOT}/toolchain/${OS_SUBDIR_SHORT}_x86
- ;;
-*)
- readonly NACL_SDK_BASE=${NACL_SDK_ROOT}/toolchain/${OS_SUBDIR_SHORT}_x86_glibc
- ;;
-esac
-fi
-
-readonly NACL_BIN_PATH=${NACL_SDK_BASE}/bin
-export NACLCC=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}gcc
-export NACLCXX=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}g++
-export NACLAR=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}ar
-export NACLRANLIB=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}ranlib
-export NACLLD=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}ld
-export NACLAS=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}as
-
-# NACL_SDK_GCC_SPECS_PATH is where nacl-gcc 'specs' file will be installed
-readonly NACL_SDK_GCC_SPECS_PATH=${NACL_SDK_BASE}/lib/gcc/x86_64-nacl/4.4.3
-
-# NACL_SDK_USR is where the headers, libraries, etc. will be installed
-readonly NACL_SDK_USR=${NACL_SDK_BASE}/${NACL_CROSS_PREFIX}/usr
-readonly NACL_SDK_USR_INCLUDE=${NACL_SDK_USR}/include
-readonly NACL_SDK_USR_LIB=${NACL_SDK_USR}/lib
-
-
-######################################################################
-# Helper functions
-######################################################################
-
-Banner() {
- echo "######################################################################"
- echo $*
- echo "######################################################################"
-}
-
-
-VerifyPath() {
- # make sure path isn't all slashes (possibly from an unset variable)
- local PATH=$1
- local TRIM=${PATH##/}
- if [ ${#TRIM} -ne 0 ]; then
- return 0
- else
- return 1
- fi
-}
-
-
-ChangeDir() {
- local NAME=$1
- if VerifyPath ${NAME}; then
- cd ${NAME}
- else
- echo "ChangeDir called with bad path."
- exit -1
- fi
-}
-
-
-Remove() {
- local NAME=$1
- if VerifyPath ${NAME}; then
- rm -rf ${NAME}
- else
- echo "Remove called with bad path."
- exit -1
- fi
-}
-
-
-MakeDir() {
- local NAME=$1
- if VerifyPath ${NAME}; then
- mkdir -p ${NAME}
- else
- echo "MakeDir called with bad path."
- exit -1
- fi
-}
-
-
-PatchSpecFile() {
- # fix up spaces so gcc sees entire path
- local SED_SAFE_SPACES_USR_INCLUDE=${NACL_SDK_USR_INCLUDE/ /\ /}
- local SED_SAFE_SPACES_USR_LIB=${NACL_SDK_USR_LIB/ /\ /}
- # have nacl-gcc dump specs file & add include & lib search paths
- ${NACL_SDK_BASE}/bin/x86_64-nacl-gcc -dumpspecs |\
- sed "/*cpp:/{
- N
- s|$| -I${SED_SAFE_SPACES_USR_INCLUDE}|
- }" |\
- sed "/*link_libgcc:/{
- N
- s|$| -L${SED_SAFE_SPACES_USR_LIB}|
- }" >${NACL_SDK_GCC_SPECS_PATH}/specs
-}
-
-
-DefaultConfigureStep() {
- Banner "Configuring ${PACKAGE_NAME}"
- # export the nacl tools
- export CC=${NACLCC}
- export CXX=${NACLCXX}
- export AR=${NACLAR}
- export RANLIB=${NACLRANLIB}
- export PKG_CONFIG_PATH=${NACL_SDK_USR_LIB}/pkgconfig
- export PKG_CONFIG_LIBDIR=${NACL_SDK_USR_LIB}
- export PATH=${NACL_BIN_PATH}:${PATH};
- ChangeDir ${NACL_PACKAGES_REPOSITORY}/${PACKAGE_NAME}
- Remove ${PACKAGE_NAME}-build
- MakeDir ${PACKAGE_NAME}-build
- cd ${PACKAGE_NAME}-build
- ../configure \
- --host=nacl \
- --disable-shared \
- --prefix=${NACL_SDK_USR} \
- --exec-prefix=${NACL_SDK_USR} \
- --libdir=${NACL_SDK_USR_LIB} \
- --oldincludedir=${NACL_SDK_USR_INCLUDE} \
- --with-http=off \
- --with-html=off \
- --with-ftp=off \
- --with-x=no
-}
-
-
-DefaultBuildStep() {
- # assumes pwd has makefile
- make clean
-if [ $TARGET_BITSIZE == "64" ]; then
- make -j8
-else
- make
-fi
-}
-
-
-DefaultInstallStep() {
- # assumes pwd has makefile
- make install
-}
-
-
-DefaultCleanUpStep() {
- PatchSpecFile
- ChangeDir ${SAVE_PWD}
-}
-
-
-DefaultPackageInstall() {
- DefaultPreInstallStep
- DefaultDownloadStep
- DefaultExtractStep
- DefaultPatchStep
- DefaultConfigureStep
- DefaultBuildStep
- DefaultInstallStep
- DefaultCleanUpStep
-}
+++ /dev/null
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-ac_cv_func_mmap=${ac_cv_func_mmap=no}
-ac_cv_var_timezone=${ac_cv_var_timezone=yes}
-ac_cv_host=${ac_cv_host=i686-pc-nacl}
-ac_cv_target=${ac_cv_target=i686-pc-nacl}
-ac_cv_func_backtrace_symbols=${ac_cv_func_backtrace_symbols=no}
-mono_cv_uscore=${mono_cv_uscore=no}
+++ /dev/null
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-ac_cv_func_mmap=${ac_cv_func_mmap=no}
-ac_cv_var_timezone=${ac_cv_var_timezone=yes}
-ac_cv_host=${ac_cv_host=x86_64-pc-nacl}
-ac_cv_target=${ac_cv_target=x86_64-pc-nacl}
-ac_cv_func_backtrace_symbols=${ac_cv_func_backtrace_symbols=no}
-mono_cv_uscore=${mono_cv_uscore=no}
+++ /dev/null
-#!/bin/bash
-# Copyright (c) 2009 The Native Client Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that be
-# found in the LICENSE file.
-#
-
-# nacl-runtime-mono.sh
-#
-# usage: nacl-runtime-mono.sh
-#
-# this script builds mono runtime for Native Client
-#
-
-readonly MONO_TRUNK_NACL=$(pwd)
-
-source common.sh
-
-readonly PACKAGE_NAME=runtime${TARGET_BIT_PREFIX}-build
-readonly INSTALL_PATH=${MONO_TRUNK_NACL}/naclmono-${CROSS_ID}
-
-
-CustomConfigureStep() {
- Banner "Configuring ${PACKAGE_NAME}"
- # export the nacl tools
- set +e
- if [ -f ${PACKAGE_NAME}/Makefile ]
- then
- cd ${PACKAGE_NAME}
- fi
- make distclean
- cd ${MONO_TRUNK_NACL}
- set -e
- if [ $TARGET_BITSIZE == "32" ]; then
- CONFIG_OPTS="--host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --target=i686-pc-linux-gnu"
- else
- CONFIG_OPTS="--host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --target=x86_64-pc-linux-gnu"
- fi
- # UGLY hack to allow dynamic linking
- sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ ../configure
- sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ ../libgc/configure
- sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ ../eglib/configure
- Remove ${PACKAGE_NAME}
- MakeDir ${PACKAGE_NAME}
- cd ${PACKAGE_NAME}
- CC=${NACLCC} CXX=${NACLCXX} AR=${NACLAR} RANLIB=${NACLRANLIB} PKG_CONFIG_PATH=${NACL_SDK_USR_LIB}/pkgconfig LD="${NACLLD}" \
- PKG_CONFIG_LIBDIR=${NACL_SDK_USR_LIB} PATH=${NACL_BIN_PATH}:${PATH} LIBS="-lnacl_dyncode -lc -lg -lnosys -lnacl" \
- CFLAGS="-g -O2 -D_POSIX_PATH_MAX=256 -DPATH_MAX=256" ../../configure \
- ${CONFIG_OPTS} \
- --exec-prefix=${INSTALL_PATH} \
- --libdir=${INSTALL_PATH}/lib \
- --prefix=${INSTALL_PATH} \
- --program-prefix="" \
- --oldincludedir=${INSTALL_PATH}/include \
- --with-glib=embedded \
- --with-tls=pthread \
- --enable-threads=posix \
- --without-sigaltstack \
- --without-mmap \
- --with-gc=included \
- --enable-nacl-gc \
- --with-sgen=no \
- --enable-nls=no \
- --enable-nacl-codegen \
- --disable-system-aot \
- --enable-shared \
- --disable-parallel-mark \
- --with-static-mono=no
-
-}
-
-CustomInstallStep() {
- make install
-}
-
-CustomPackageInstall() {
- CustomConfigureStep
- DefaultBuildStep
- CustomInstallStep
-}
-
-CustomPackageInstall
-exit 0
+++ /dev/null
-#!/bin/bash
-# Copyright (c) 2012 The Native Client Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# Usage: nacl_interp_loader.sh PLATFORM NEXE ARGS...
-
-# Assumes this file is sitting in the source tree.
-# This should be changed for some proper SDK installation setup.
-NACL_SDK_ROOT=${NACL_SDK_ROOT:-/path/to/naclsdk/pepper_XX}
-
-case "$1" in
-i?86)
- arch=x86_32
- libdir=lib32
- ;;
-x86_64)
- arch=x86_64
- libdir=lib64
- ;;
-arm|v7l)
- arch=arm
- libdir=lib32
- ;;
-*)
- echo >&2 "$0: Do not recognize architecture \"$1\""
- exit 127
- ;;
-esac
-
-shift
-
-case "${NACL_SDK_ROOT}" in
-*pepper_15* | *pepper_16* | *pepper_17*)
- SEL_LDR="$NACL_SDK_ROOT/toolchain/linux_x86/bin/sel_ldr_${arch}"
- IRT="$NACL_SDK_ROOT/toolchain/linux_x86/runtime/irt_core_${arch}.nexe"
- RTLD="$NACL_SDK_ROOT/toolchain/linux_x86/x86_64-nacl/${libdir}/runnable-ld.so"
- LIBDIR="$NACL_SDK_ROOT/toolchain/linux_x86/x86_64-nacl/${libdir}"
- ;;
-*)
- SEL_LDR="$NACL_SDK_ROOT/tools/sel_ldr_${arch}"
- IRT="$NACL_SDK_ROOT/tools/irt_core_${arch}.nexe"
- RTLD="$NACL_SDK_ROOT/toolchain/linux_x86_glibc/x86_64-nacl/${libdir}/runnable-ld.so"
- LIBDIR="$NACL_SDK_ROOT/toolchain/linux_x86_glibc/x86_64-nacl/${libdir}"
- ;;
-esac
-
-IGNORE_VALIDATOR_ARG=""
-if [ x"$NACL_IGNORE_VALIDATOR" == x"1" ]; then
- IGNORE_VALIDATOR_ARG="-c"
-fi
-
-exec "$SEL_LDR" -E "NACL_PWD=`pwd`" -E "MONO_PATH=$MONO_PATH" \
- -E "MONO_CFG_DIR=$MONO_CFG_DIR" -E "MONO_SHARED_DIR=$MONO_SHARED_DIR" \
- -a $IGNORE_VALIDATOR_ARG -S -B "$IRT" -l /dev/null -- "$RTLD" \
- --library-path $LIBDIR "$@"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "resx2sr-net_4_x", "mcs/tools/resx2sr/resx2sr-net_4_x.csproj", "{07D30676-A919-4763-8C3C-B2C4DAFFC662}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "al-net_4_x", "mcs/tools/al/al-net_4_x.csproj", "{D237CE6E-EA8F-4E8E-8413-295B27714AC6}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "monolinker-net_4_x", "mcs/tools/linker/monolinker-net_4_x.csproj", "{FA920637-C202-4E75-AC0F-1A8DBD631DF1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "al-net_4_x", "mcs/tools/al/al-net_4_x.csproj", "{D237CE6E-EA8F-4E8E-8413-295B27714AC6}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "genxs-net_4_x", "mcs/tools/genxs/genxs-net_4_x.csproj", "{DCD2613C-B1A0-489B-BCA1-79BEBB9B9541}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mkbundle-net_4_x", "mcs/tools/mkbundle/mkbundle-net_4_x.csproj", "{3A3DAEC2-3DF4-4968-A191-8D6F207ABA5E}"
{07D30676-A919-4763-8C3C-B2C4DAFFC662}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07D30676-A919-4763-8C3C-B2C4DAFFC662}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07D30676-A919-4763-8C3C-B2C4DAFFC662}.Release|Any CPU.Build.0 = Release|Any CPU
- {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Release|Any CPU.Build.0 = Release|Any CPU
{FA920637-C202-4E75-AC0F-1A8DBD631DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA920637-C202-4E75-AC0F-1A8DBD631DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA920637-C202-4E75-AC0F-1A8DBD631DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA920637-C202-4E75-AC0F-1A8DBD631DF1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D237CE6E-EA8F-4E8E-8413-295B27714AC6}.Release|Any CPU.Build.0 = Release|Any CPU
{DCD2613C-B1A0-489B-BCA1-79BEBB9B9541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DCD2613C-B1A0-489B-BCA1-79BEBB9B9541}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCD2613C-B1A0-489B-BCA1-79BEBB9B9541}.Release|Any CPU.ActiveCfg = Release|Any CPU
GitHubTarballPackage(
'mono',
'libgdiplus',
- '2.11',
- '4e7ab0f555a13a6b2f954c714c4ee5213954ff79',
+ '5.4',
+ '350eb49a45ca5a7383c01d49df72438347a5dbc9',
configure='CFLAGS="%{gcc_flags} %{local_gcc_flags} -I/opt/X11/include" ./autogen.sh --prefix="%{package_prefix}"',
override_properties={
'make': 'C_INCLUDE_PATH="" make'})
"LocalMachine")
ensure_dir(registry_dir)
- # Add ImportBefore/ImportAfter files from xbuild to the msbuild
- # directories
+ # Add ImportBefore files from xbuild 14.0 toolsVersion directory to msbuild's
+ # 15.0 directory
xbuild_dir = os.path.join(self.staged_prefix, 'lib/mono/xbuild')
- new_xbuild_tv_dir = os.path.join(xbuild_dir, self.version)
+ new_xbuild_tv_dir = os.path.join(xbuild_dir, '15.0')
os.makedirs(new_xbuild_tv_dir)
self.sh('cp -R %s/14.0/Imports %s' % (xbuild_dir, new_xbuild_tv_dir))
- self.sh(
- 'cp -R %s/14.0/Microsoft.Common.targets %s' %
- (xbuild_dir, new_xbuild_tv_dir))
+
+ for dep in glob.glob("%s/Microsoft/NuGet/*" % xbuild_dir):
+ self.sh('ln -s %s %s' % (dep, xbuild_dir))
def deploy(self):
if bockbuild.cmd_options.arch == 'darwin-universal':
class MSBuild (GitHubPackage):
def __init__ (self):
- GitHubPackage.__init__ (self, 'mono', 'msbuild', '15.0',
+ GitHubPackage.__init__ (self, 'mono', 'msbuild', '15.3',
git_branch = 'xplat-master')
def build (self):
Package.__init__(self, 'xamarin-gtk-theme',
sources=[
'git://github.com/mono/xamarin-gtk-theme.git'],
- revision='cc3fb66e56d494e968be3a529a0737a60e31c1f3')
+ revision='b7fe407d869dfeac4eacbcb82771f600e0bbaa83')
def build(self):
try:
Package.__init__(self, 'mono-extensions', None,
sources=['git@github.com:xamarin/mono-extensions.git'],
git_branch=self.profile.release_packages[
- 'mono'].git_branch
+ 'mono'].git_branch,
+ revision='07ad37d63e0e9dcf7c879a72bc14c5d6c794f7b6'
)
self.source_dir_name = 'mono-extensions'
--- /dev/null
+mono-MDK-windows crlf=input
+mono-MDK-windows-x64 crlf=input
+defs/gtksharp crlf=input
+defs/managed-components crlf=input
+defs/mono crlf=input
+defs/mono64 crlf=input
--- /dev/null
+#!/bin/bash -xe
+
+REPO="https://dl.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.44.msi"
+REPODIR=$(dirname $(realpath $0))/../repos/gtksharp
+
+error()
+{
+ echo "$(date "+%F@%T") :: $1" 1>&2
+ exit 1
+}
+
+report()
+{
+ echo "$(date "+%F@%T") :: $1"
+}
+
+download()
+{
+ mkdir -p ${REPODIR}
+ if [ ! -d "${REPODIR}/lessmsi" ]
+ then report "Downloading LessMSIerables"
+ wget --quiet -O ${REPODIR}/lessmsi.zip https://github.com/activescott/lessmsi/releases/download/v1.2.0/lessmsi-v1.2.0.zip
+ mkdir -p ${REPODIR}/lessmsi
+ unzip -d ${REPODIR}/lessmsi ${REPODIR}/lessmsi.zip
+ chmod a+x ${REPODIR}/lessmsi/*.exe ${REPODIR}/lessmsi/*.dll
+ fi
+ report "Downloading GTK# for Windows - ${REPO}"
+ wget --quiet -O ${REPODIR}/gtksharp.msi ${REPO}
+}
+
+clean()
+{
+ pushd ${REPODIR}
+ report "Deleting interstitial output"
+ rm -rf ${REPODIR}/gtksharp
+ popd
+}
+
+build()
+{
+ pushd ${REPODIR}
+ report "Unpacking GTK# for Windows"
+ mkdir -p gtksharp
+ pushd lessmsi
+ ./lessmsi.exe x ../gtksharp.msi
+ mv gtksharp/SourceDir/PFiles/GtkSharp/2.12/* ../gtksharp
+ rm -rf gtksharp
+ popd
+ popd
+}
+
+install()
+{
+ pushd ${REPODIR}
+ cp -r gtksharp/etc/* ../../tmp/mono/etc/
+ cp -r gtksharp/bin/* ../../tmp/mono/bin/
+ cp -r gtksharp/lib/* ../../tmp/mono/lib/
+ cp -r gtksharp/share/* ../../tmp/mono/share/
+ pushd ../../tmp/mono/
+ for i in lib/gtk-sharp-2.0/*.dll
+ do bin/gacutil -i $i
+ done
+ popd
+ cp -r ../../resources/pkgconfig ../../tmp/mono/lib/
+ popd
+}
+
+prerequisites()
+{
+ which msiexec 2>/dev/null || error "*** msiexec is not in \$PATH ***"
+}
+
+$@
--- /dev/null
+#!/bin/bash -xe
+
+REPODIR=$(dirname $(realpath $0))/../repos/managed-components
+
+error()
+{
+ echo "$(date "+%F@%T") :: $1" 1>&2
+ exit 1
+}
+
+report()
+{
+ echo "$(date "+%F@%T") :: $1"
+}
+
+download()
+{
+ mkdir -p ${REPODIR}
+ report "Downloading Xar"
+ wget --quiet -O ${REPODIR}/xar.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz || error "*** Could not download Xar ***"
+ report "Copying Mono MDK for Mac"
+ cp ${2} ${REPODIR}/mono.xar
+}
+
+clean()
+{
+ pushd ${REPODIR}
+ report "Deleting interstitial output"
+ rm -rf ${REPODIR}/mono-mac \
+ ${REPODIR}/xar \
+ ${REPODIR}/Distribution \
+ ${REPODIR}/mono.pkg \
+ ${REPODIR}/Resources \
+ ${REPODIR}/Library \
+ ${REPODIR}/../../tmp/mono-mac
+ popd
+}
+
+build()
+{
+ pushd ${REPODIR}
+ if [ ! -x "${REPODIR}/xar/src/xar" ]
+ then report "Building Xar"
+ mkdir -p xar
+ tar xf xar.tar.gz -C xar/ --strip-components=1
+ pushd xar/
+ ./configure
+ make
+ popd
+ fi
+ report "Unpacking Mono for Mac"
+ xar/src/xar -x -f mono.xar
+ zcat mono.pkg/Payload | bsdcpio -i
+ mv Library/Frameworks/Mono.framework/Versions/5.* mono-mac
+ popd
+}
+
+install()
+{
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/xsp ${REPODIR}/../../tmp/mono/lib/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/Microsoft* ${REPODIR}/../../tmp/mono/lib/mono/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/msbuild ${REPODIR}/../../tmp/mono/lib/mono/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/nuget ${REPODIR}/../../tmp/mono/lib/mono/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/xbuild-frameworks ${REPODIR}/../../tmp/mono/lib/mono/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/gac/FSharp.Core/4.4.1.0__b03f5f7f11d50a3a/FSharp* ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/gac/nunit*/2.4.8.0__96d09a1eb7f44a77/*.dll* ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.5/Microsoft.VisualBasic.dll ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.5/Mono.Cecil.VB* ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.5/Mono.WebServer2.dll ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.5/vbnc.* ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.5/xsp4.exe ${REPODIR}/../../tmp/mono/lib/mono/4.5/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/fsharp ${REPODIR}/../../tmp/mono/lib/mono/
+ rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/4.0-api/Microsoft.VisualBasic.dll ${REPODIR}/../../tmp/mono/lib/mono/4.0-api/
+ rsync -a --copy-links ${REPODIR}/mono-mac/bin/fsharp* ${REPODIR}/../../tmp/mono/bin/
+ rsync -a --copy-links ${REPODIR}/mono-mac/bin/xsp* ${REPODIR}/../../tmp/mono/bin/
+ rsync -a --copy-links ${REPODIR}/mono-mac/bin/nuget ${REPODIR}/../../tmp/mono/bin/
+ rsync -a --copy-links ${REPODIR}/mono-mac/bin/msbuild ${REPODIR}/../../tmp/mono/bin/
+ sed -i 's#/Library.*mono#../..#' ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ F\#/v4.*/*
+ sed -i 's#/Library.*mono#../../../../..#' ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/3.*/Framework/v4.*/*
+ rsync -a --copy-links ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ F\#/v4.0/* ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ F\#/v4.0/
+ rsync -a --copy-links ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/3.0/Framework/v4.0/* ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/3.0/Framework/v4.0/
+ rsync -a --copy-links ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/3.1/Framework/v4.0/* ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/3.1/Framework/v4.0/
+ rsync -a --copy-links ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/4.0/Framework/v4.0/* ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/4.0/Framework/v4.0/
+ rsync -a --copy-links ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/4.1/Framework/v4.0/* ${REPODIR}/../../tmp/mono/lib/mono/Microsoft\ SDKs/F\#/4.1/Framework/v4.0/
+ pushd ${REPODIR}/../../tmp/mono/bin
+ rm -f xsp
+ for i in xsp2 xsp4 fsharpc fsharpi fsharpiAnyCpu nuget msbuild
+ do echo "Processing $i"
+ sed -i 's#/Library.*mono #\"\$\{BASH_SOURCE%/\*\}\"/mono #' $i
+ sed -i 's#/Library.*cli #\"\$\{BASH_SOURCE%/\*\}\"/cli #' $i
+ if [ -n "$(grep -hoE '[\" ]/Library.*\.(exe|dll)' $i)" ]
+ then EXENAME=$(basename `grep -hoE -m 1 '[\" ]/Library.*\.(exe|dll)' $i | sed 's/^\"//'`)
+ RUNTIME=$(dirname `grep -hoE -m 1 '[\" ]/Library.*\.(exe|dll)' $i` | sed 's/^\"//' | sed 's#/Library.*/[0-9]\+\.[0-9]\+\.[0-9]\+/lib/##' | sed '/^mono\//! s#^#..\\\\#' | sed 's#^mono/##')
+ sed "s#@@RUNTIME@@#${RUNTIME}\\\\#g" ${REPODIR}/../../resources/wrapper.bat > $i.bat
+ sed -i "s#@@COMMAND@@#${EXENAME}#g" $i.bat
+ sed -i 's#/#\\#g' $i.bat
+ fi
+ sed -i 's#/Library.*/[0-9]\+\.[0-9]\+\.[0-9]\+/lib/#\"\$\(cygpath -w \"\$\{BASH_SOURCE%/\*\}\"/../lib/\)\"#g#' $i
+ sed -i 's#\"\"#\"#g' $i
+ sed -i 's#)\"#)#g' $i
+ sed -i 's#exe #exe\" #' $i
+ sed -i 's#dll #dll\" #' $i
+ sed -i 's#basename \$0#basename \"\$0\"#' $i
+ done
+ cp xsp4 xsp
+ cp xsp4.bat xsp.bat
+ chmod a+x *
+ cd ..
+ for i in lib/mono/4.5/Mono.Cecil.VB*.dll lib/mono/4.5/Microsoft.VisualBasic.dll lib/mono/*/xsp*.exe lib/mono/*/FSharp*.dll lib/mono/*/Mono.WebServer*.dll ../../repos/managed-components/mono-mac/lib/mono/gac/FSharp.Core/4.3*/FSharp.Core.dll ../../repos/managed-components/mono-mac/lib/mono/gac/FSharp.Core/4.4.0*/FSharp.Core.dll
+ do bin/gacutil -i $i
+ done
+ rsync -a --copy-links lib/mono/4.5/FSharp.Core.*data lib/mono/gac/FSharp.Core/4.4.1.0__*/
+ rsync -a --copy-links lib/mono/4.5/FSharp.Core.*data lib/mono/gac/FSharp.Core/4.4.0.0__*/
+ rsync -a --copy-links lib/mono/4.5/FSharp.Core.*data lib/mono/gac/FSharp.Core/4.3.1.0__*/
+ rsync -a --copy-links lib/mono/4.5/FSharp.Core.*data lib/mono/gac/FSharp.Core/4.3.0.0__*/
+ popd
+}
+
+prerequisites()
+{
+ which bsdcpio 2>/dev/null || error "*** bsdcpio is not in \$PATH ***"
+ which wget 2>/dev/null || error "*** wget is not in \$PATH ***"
+ which xml2-config 2>/dev/null || error "*** xml2-config is not in \$PATH ***"
+ if [ ! -e "/usr/include/openssl/crypto.h" ]
+ then error "*** openssl-devel is not installed ***"
+ fi
+}
+
+$@
--- /dev/null
+#!/bin/bash -xe
+
+REPODIR=$(dirname $(realpath $0))/../../..
+INSTALLDIR=$(realpath -m $(dirname $0)/../tmp/mono)
+
+error()
+{
+ echo "$(date "+%F@%T") :: $1" 1>&2
+ exit 1
+}
+
+report()
+{
+ echo "$(date "+%F@%T") :: $1"
+}
+
+download()
+{
+ wget --quiet -O ${REPODIR}/pkgconfig.zip http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/pkg-config_0.26-1_win32.zip
+}
+
+clean()
+{
+ rm -rf ${INSTALLDIR}
+}
+
+build()
+{
+ pushd ${REPODIR}
+ report "Building Mono"
+ mkdir -p ${INSTALLDIR}
+ WORKSPACE=${REPODIR} EXTRA_CONF_FLAGS="--prefix=${INSTALLDIR}" ghprbPullId=1 CI_TAGS="no-tests" label="w32" scripts/ci/run-jenkins.sh || error "*** Could not run autogen ***"
+ popd
+}
+
+install()
+{
+ pushd ${REPODIR}
+ MONO_EXECUTABLE=${REPODIR}/msvc/build/sgen/Win32/bin/Release/mono-sgen.exe make install || error "*** Installing to temporary prefix failed ***"
+ rm -f ${INSTALLDIR}/bin/mono-sgen.* \
+ ${INSTALLDIR}/bin/mono-boehm.* \
+ ${INSTALLDIR}/lib/libmono-2.0.* \
+ ${INSTALLDIR}/lib/libmonoboehm-2.0.* \
+ ${INSTALLDIR}/lib/libmonosgen-2.0.* \
+ ${INSTALLDIR}/bin/MonoPosixHelper.* \
+ ${INSTALLDIR}/lib/MonoPosixHelper.* \
+ ${INSTALLDIR}/bin/mono \
+ ${INSTALLDIR}/bin/pedump \
+ ${INSTALLDIR}/bin/mono-package-runtime \
+ ${INSTALLDIR}/bin/monodis*
+ pushd ${REPODIR}
+ cp -a msvc/build/sgen/Win32/bin/Release/monodis-sgen.exe ${INSTALLDIR}/bin/monodis.exe
+ cp -a msvc/build/sgen/Win32/bin/Release/monodis-sgen.pdb ${INSTALLDIR}/bin/monodis.pdb
+ cp -a msvc/build/sgen/Win32/bin/Release/mono-sgen.exe ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/Win32/bin/Release/mono-sgen.pdb ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/Win32/bin/Release/mono-2.0-sgen.dll ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/Win32/lib/Release/mono-2.0-sgen.lib ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/Win32/bin/Release/mono-2.0-sgen.pdb ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/Win32/bin/Release/MonoPosixHelper.dll ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/Win32/lib/Release/MonoPosixHelper.lib ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/Win32/bin/Release/MonoPosixHelper.pdb ${INSTALLDIR}/lib/
+ cp -a msvc/build/boehm/Win32/bin/Release/mono-boehm.exe ${INSTALLDIR}/bin/
+ cp -a msvc/build/boehm/Win32/bin/Release/mono-boehm.pdb ${INSTALLDIR}/bin/
+ cp -a msvc/build/boehm/Win32/bin/Release/mono-2.0-boehm.dll ${INSTALLDIR}/bin/
+ cp -a msvc/build/boehm/Win32/lib/Release/mono-2.0-boehm.lib ${INSTALLDIR}/lib/
+ cp -a msvc/build/boehm/Win32/bin/Release/mono-2.0-boehm.pdb ${INSTALLDIR}/lib/
+ cp -a ${INSTALLDIR}/bin/mono-sgen.exe ${INSTALLDIR}/bin/mono.exe
+ cp -a ${INSTALLDIR}/bin/mono-sgen.pdb ${INSTALLDIR}/bin/mono.pdb
+ popd
+ pushd ${INSTALLDIR}/bin
+ for i in *
+ do if [[ "`file -b $i`" == "POSIX shell script, ASCII text"* ]]
+ then RUNTIME=`grep -ho -m 1 "xbuild/.*/bin/\|[2,3,4]\.[0,5]/" $i | sed 's#/$##'`
+ if [ -n "$(grep -ho '.:/.*\.exe' $i)" ]
+ then EXENAME=$(basename `grep -ho '.:/.*\.exe' $i`)
+ fi
+ if [ -f "../lib/mono/${RUNTIME}/${EXENAME}" ]
+ then sed "s#@@RUNTIME@@#${RUNTIME}#g" $(dirname $0)/../resources/wrapper.bat > $i.bat
+ sed -i "s#@@COMMAND@@#${EXENAME}#g" $i.bat
+ sed -i 's#/#\\#g' $i.bat
+ fi
+ sed -i "s#.:/.*/#\"\$\(cygpath -w \"\$\{BASH_SOURCE%/\*\}\"/../lib/mono/${RUNTIME}/\)\"#g" $i
+ sed -i 's#/.*/tmp/mono/bin#\"\$\{BASH_SOURCE%/\*\}\"#g' $i
+ fi
+ done
+ unzip -jd . ${REPODIR}/pkgconfig.zip bin/pkg-config.exe
+ chmod a+x *.bat *.exe
+ popd
+ popd
+}
+
+prerequisites()
+{
+ which mcs 2>/dev/null || error "*** mcs is not in \$PATH ***"
+}
+
+$@
--- /dev/null
+#!/bin/bash -xe
+
+REPODIR=$(dirname $(realpath $0))/../../..
+INSTALLDIR=$(realpath -m $(dirname $0)/../tmp/mono)
+
+error()
+{
+ echo "$(date "+%F@%T") :: $1" 1>&2
+ exit 1
+}
+
+report()
+{
+ echo "$(date "+%F@%T") :: $1"
+}
+
+download()
+{
+ wget --quiet -O ${REPODIR}/pkgconfig.zip http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/pkg-config_0.26-1_win32.zip
+}
+
+clean()
+{
+ rm -rf ${INSTALLDIR}
+}
+
+build()
+{
+ pushd ${REPODIR}
+ report "Building Mono"
+ mkdir -p ${INSTALLDIR}
+ WORKSPACE=${REPODIR} EXTRA_CONF_FLAGS="--prefix=${INSTALLDIR}" ghprbPullId=1 CI_TAGS="no-tests" label="w64" scripts/ci/run-jenkins.sh || error "*** Could not run autogen ***"
+ popd
+}
+
+install()
+{
+ pushd ${REPODIR}
+ MONO_EXECUTABLE=${REPODIR}/msvc/build/sgen/x64/bin/Release/mono-sgen.exe make install || error "*** Installing to temporary prefix failed ***"
+ rm -f ${INSTALLDIR}/bin/mono-sgen.* \
+ ${INSTALLDIR}/bin/mono-boehm.* \
+ ${INSTALLDIR}/lib/libmono-2.0.* \
+ ${INSTALLDIR}/lib/libmonoboehm-2.0.* \
+ ${INSTALLDIR}/lib/libmonosgen-2.0.* \
+ ${INSTALLDIR}/bin/MonoPosixHelper.* \
+ ${INSTALLDIR}/lib/MonoPosixHelper.* \
+ ${INSTALLDIR}/bin/mono \
+ ${INSTALLDIR}/bin/pedump \
+ ${INSTALLDIR}/bin/mono-package-runtime \
+ ${INSTALLDIR}/bin/monodis*
+ pushd ${REPODIR}
+ cp -a msvc/build/sgen/x64/bin/Release/monodis-sgen.exe ${INSTALLDIR}/bin/monodis.exe
+ cp -a msvc/build/sgen/x64/bin/Release/monodis-sgen.pdb ${INSTALLDIR}/bin/monodis.pdb
+ cp -a msvc/build/sgen/x64/bin/Release/mono-sgen.exe ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/x64/bin/Release/mono-sgen.pdb ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/x64/bin/Release/mono-2.0-sgen.dll ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/x64/lib/Release/mono-2.0-sgen.lib ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/x64/bin/Release/mono-2.0-sgen.pdb ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/x64/bin/Release/MonoPosixHelper.dll ${INSTALLDIR}/bin/
+ cp -a msvc/build/sgen/x64/lib/Release/MonoPosixHelper.lib ${INSTALLDIR}/lib/
+ cp -a msvc/build/sgen/x64/bin/Release/MonoPosixHelper.pdb ${INSTALLDIR}/lib/
+ cp -a ${INSTALLDIR}/bin/mono-sgen.exe ${INSTALLDIR}/bin/mono.exe
+ cp -a ${INSTALLDIR}/bin/mono-sgen.pdb ${INSTALLDIR}/bin/mono.pdb
+ popd
+ pushd ${INSTALLDIR}/bin
+ for i in *
+ do if [[ "`file -b $i`" == "POSIX shell script, ASCII text"* ]]
+ then RUNTIME=`grep -ho -m 1 "xbuild/.*/bin/\|[2,3,4]\.[0,5]/" $i | sed 's#/$##'`
+ if [ -n "$(grep -ho '.:/.*\.exe' $i)" ]
+ then EXENAME=$(basename `grep -ho '.:/.*\.exe' $i`)
+ fi
+ if [ -f "../lib/mono/${RUNTIME}/${EXENAME}" ]
+ then sed "s#@@RUNTIME@@#${RUNTIME}#g" $(dirname $0)/../resources/wrapper.bat > $i.bat
+ sed -i "s#@@COMMAND@@#${EXENAME}#g" $i.bat
+ sed -i 's#/#\\#g' $i.bat
+ fi
+ sed -i "s#.:/.*/#\"\$\(cygpath -w \"\$\{BASH_SOURCE%/\*\}\"/../lib/mono/${RUNTIME}/\)\"#g" $i
+ sed -i 's#/.*/tmp/mono/bin#\"\$\{BASH_SOURCE%/\*\}\"#g' $i
+ fi
+ done
+ unzip -jd . ${REPODIR}/pkgconfig.zip bin/pkg-config.exe
+ chmod a+x *.bat *.exe
+ popd
+ popd
+}
+
+prerequisites()
+{
+ which mcs 2>/dev/null || error "*** mcs is not in \$PATH ***"
+}
+
+$@
--- /dev/null
+#!/bin/bash
+COMPONENTS="mono gtksharp managed-components"
+for i in ${COMPONENTS}
+ do defs/$i prerequisites
+done
+COMPONENTS="gtksharp managed-components"
+defs/mono download
+defs/gtksharp download
+defs/managed-components download ${mdk}
+COMPONENTS="mono gtksharp managed-components"
+for i in ${COMPONENTS}
+ do defs/$i clean
+ defs/$i build
+ defs/$i install
+done
+resources/build.bat
--- /dev/null
+#!/bin/bash
+COMPONENTS="mono64 managed-components"
+for i in ${COMPONENTS}
+ do defs/$i prerequisites
+done
+COMPONENTS="managed-components"
+defs/mono64 download
+defs/managed-components download ${mdk}
+COMPONENTS="mono64 managed-components"
+for i in ${COMPONENTS}
+ do defs/$i clean
+ defs/$i build
+ defs/$i install
+done
+resources/build64.bat
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>3.9</ProductVersion>
+ <ProjectGuid>9f279b8c-fc0d-49d4-b5bd-ade0db0c3095</ProjectGuid>
+ <SchemaVersion>2.0</SchemaVersion>
+ <OutputName>MonoForWindows-$(Platform)</OutputName>
+ <OutputType>Package</OutputType>
+ <SuppressIces>ICE61;</SuppressIces>
+ <DefineSolutionProperties>false</DefineSolutionProperties>
+ <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
+ <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <OutputPath>bin\$(Configuration)\</OutputPath>
+ <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
+ <DefineConstants>Debug</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\$(Configuration)\</OutputPath>
+ <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
+ <DefineConstants>
+ </DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <OutputPath>bin\$(Configuration)\</OutputPath>
+ <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
+ <DefineConstants>Debug</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\$(Configuration)\</OutputPath>
+ <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
+ <DefineConstants>
+ </DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="mono.generated.wxs" />
+ <Compile Include="Product.wxs" />
+ </ItemGroup>
+ <ItemGroup>
+ <WixExtension Include="WixUIExtension">
+ <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
+ <Name>WixUIExtension</Name>
+ </WixExtension>
+ </ItemGroup>
+ <Import Project="$(WixTargetsPath)" />
+ <Target Name="BeforeBuild">
+ <HeatDirectory OutputFile="mono.generated.wxs" Directory="$(MONO_FILES_DIR)" DirectoryRefId="INSTALLFOLDER" ComponentGroupName="MonoFiles" PreprocessorVariable="env.MONO_FILES_DIR" ToolPath="$(WixToolPath)" GenerateGuidsNow="true" SuppressCom="true" SuppressRegistry="true" SuppressFragments="true" SuppressRootDirectory="true" />
+ </Target>
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+
+<?if $(sys.BUILDARCH)=x86 ?>
+ <?define UpgradeCode="177a37ab-9354-487f-ac97-8407195c3043" ?>
+ <?define ProgramFilesX86orX64="ProgramFilesFolder" ?>
+ <?define SystemFolderX86orX64="SystemFolder" ?>
+ <?define MonoProgramFilesGuid="9B7A0108-39DA-4332-AE40-545E28919736" ?>
+ <?define ApplicationShortcutsGuid="CF93ABFD-416B-4C10-9126-EA93BC1D7154" ?>
+<?elseif $(sys.BUILDARCH)=x64 ?>
+ <?define UpgradeCode="1f58e2dd-d88a-402d-a67f-a27e1efaaf48" ?>
+ <?define ProgramFilesX86orX64="ProgramFiles64Folder" ?>
+ <?define SystemFolderX86orX64="System64Folder" ?>
+ <?define MonoProgramFilesGuid="b4d95bcc-9fa9-48c4-a2d0-1d83f031e974" ?>
+ <?define ApplicationShortcutsGuid="8a74633a-86bb-4891-b9aa-1e7aaf7597c6" ?>
+<?else?>
+ <?error $(sys.BUILDARCH) is not supported ?>
+<?endif?>
+
+ <Product Id="*"
+ Name="Mono for Windows ($(sys.BUILDARCH))"
+ Language="1033"
+ Version="$(env.MONO_VERSION)"
+ Manufacturer="Xamarin, Inc."
+ UpgradeCode="$(var.UpgradeCode)">
+ <Package InstallerVersion="405" Compressed="yes" InstallScope="perMachine" Platform="$(sys.BUILDARCH)" />
+
+
+ <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
+ <MediaTemplate EmbedCab="yes" />
+
+ <Icon Id="app.ico" SourceFile="setup-files\app.ico"/>
+
+ <!-- Entries for the 'Add & Remove Programs' section in control panel -->
+ <Property Id="ARPPRODUCTICON" Value="app.ico" />
+ <Property Id="ARPHELPLINK" Value="http://www.mono-project.com/" />
+ <Property Id="ARPURLINFOABOUT" Value="http://www.mono-project.com/" />
+ <Property Id="ARPURLUPDATEINFO" Value="http://www.mono-project.com/docs/about-mono/releases/" />
+
+ <Property Id="MSIFASTINSTALL" Value="7" />
+
+ <Condition Message="This application is only supported on Windows Vista or higher.">
+ <![CDATA[Installed OR (VersionNT >= 600)]]>
+ </Condition>
+
+ <UIRef Id="WixUI_Minimal" />
+ <WixVariable Id="WixUILicenseRtf" Value="setup-files\license.rtf" />
+ <WixVariable Id="WixUIBannerBmp" Value="setup-files\banner.bmp" />
+ <WixVariable Id="WixUIDialogBmp" Value="setup-files\dialog.bmp" />
+
+ <Feature Id="ProductFeature" Title="Mono" Level="1">
+ <ComponentGroupRef Id="ProductComponents" />
+ </Feature>
+ <DirectoryRef Id="TARGETDIR">
+ <Merge Id="VCRedist2013" SourceFile="$(env.CommonProgramFiles(x86))\Merge Modules\Microsoft_VC120_CRT_x86.msm" DiskId="1" Language="0"/>
+ <Merge Id="VCRedist2015" SourceFile="$(env.CommonProgramFiles(x86))\Merge Modules\Microsoft_VC140_CRT_$(sys.BUILDARCH).msm" DiskId="1" Language="0"/>
+ </DirectoryRef>
+ <Feature Id="VCRedist2013" Title="Visual C++ 12.0 Runtime (x86)" AllowAdvertise="no" Display="hidden" Level="1">
+ <MergeRef Id="VCRedist2013"/>
+ </Feature>
+ <Feature Id="VCRedist2015" Title="Visual C++ 14.0 Runtime" AllowAdvertise="no" Display="hidden" Level="1">
+ <MergeRef Id="VCRedist2015"/>
+ </Feature>
+ </Product>
+
+ <Fragment>
+ <Directory Id="TARGETDIR" Name="SourceDir">
+ <Directory Id="$(var.ProgramFilesX86orX64)">
+ <Directory Id="INSTALLFOLDER" Name="Mono">
+ <Directory Id="binFolder" Name="bin">
+ <Component Id="MonoProgramFiles" Guid="$(var.MonoProgramFilesGuid)">
+ <File KeyPath="yes" Source="bat\setmonopath.bat" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="Installed" Type="integer" Value="1" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="Version" Type="string" Value="$(env.MONO_VERSION)" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="SdkInstallRoot" Type="string" Value="[INSTALLFOLDER]" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="FrameworkAssemblyDirectory" Type="string" Value="[INSTALLFOLDER]lib\" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="MonoConfigDir" Type="string" Value="[INSTALLFOLDER]etc\" />
+ <RegistryValue Root="HKLM" Key="Software\Mono" Name="Architecture" Type="string" Value="$(sys.BUILDARCH)" />
+ </Component>
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <!-- Start Menu Shortcut -->
+ <Directory Id="ProgramMenuFolder">
+ <Directory Id="ApplicationProgramsFolder" Name="Mono">
+ <Component Id="ApplicationShortcuts" Guid="$(var.ApplicationShortcutsGuid)">
+ <Shortcut Id="ApplicationStartMenuShortcutMono"
+ Name="Open Mono $(sys.BUILDARCH) Command Prompt"
+ Target="[$(var.SystemFolderX86orX64)]cmd.exe"
+ Arguments="/k "[INSTALLFOLDER]\bin\setmonopath.bat""
+ WorkingDirectory="INSTALLFOLDER"/>
+ <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
+ <RegistryValue Root="HKCU" Key="Software\Mono" Name="Installed" Type="integer" Value="1" KeyPath="yes"/>
+ </Component>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Fragment>
+
+ <Fragment>
+ <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
+ <ComponentGroupRef Id="MonoFiles" />
+ <ComponentRef Id="MonoProgramFiles" />
+ <ComponentRef Id="ApplicationShortcuts" />
+ </ComponentGroup>
+ </Fragment>
+</Wix>
--- /dev/null
+@echo off
+echo Mono version X.X.X
+echo Prepending '%~dp0' to PATH
+PATH=%~dp0;%PATH%
--- /dev/null
+@echo off
+
+set MONO_VERSION=X.X.X
+set MONO_FILES_DIR=..\tmp\mono
+
+"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" %~dp0\MonoForWindows.wixproj /p:Configuration=Release /p:DefaultCompressionLevel=high
--- /dev/null
+@echo off
+
+set MONO_VERSION=X.X.X
+set MONO_FILES_DIR=..\tmp\mono
+
+"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" %~dp0\MonoForWindows.wixproj /p:Configuration=Release /p:Platform=x64 /p:DefaultCompressionLevel=high
--- /dev/null
+{\rtf1\ansi\ansicpg10000\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset77 Arial;}{\f1\fnil\fcharset0 Arial;}}
+{\colortbl ;\red0\green0\blue255;}
+{\*\generator Riched20 10.0.15063}\viewkind4\uc1
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\f0\fs24\lang1033
+
+\f0\fs24 \cf0 In general, the runtime and its class libraries are licensed under the\
+terms of the MIT license, and some third party code is licensed under\
+the 3-clause BSD license. See the file "PATENTS.TXT" for Microsoft's\
+patent grant on the Mono codebase.\
+\
+The Mono distribution does include a handful of pieces of code that\
+are used during the build system and are covered under different\
+licenses, those include:\
+\
+Build Time Code\
+===============\
+\
+This is code that is used at build time, or during the maintenance of\
+Mono itself, and does not end up in the redistributable part of Mono:\
+\
+* gettext\
+\
+ m4 source files used to probe features at build time: GPL\
+\
+* Benchmark Source Files\
+\
+ Logic.cs and zipmark.cs are GPL source files.\
+\
+* mono/docs/HtmlAgilityPack\
+\
+ MS-PL licensed\
+\
+* mcs/jay: 4-clause BSD licensed\
+\
+* mcs/nunit24: MS-PL\
+\
+* mcs/class/I18N/mklist.sh, tools/cvt.sh: GNU GPLv2\
+\
+Runtime Code\
+============\
+\
+The following code is linked with the final Mono runtime, the libmono\
+embeddable runtime:\
+\
+* support/minizip: BSD license.\
+\
+* mono/utils/memcheck.h: BSD license, used on debug builds that use Valgrind.\
+\
+* mono/utils/freebsd-dwarf.h, freebsd-elf_common.h, freebsd-elf64.h freebsd-elf32.h: BSD license.\
+\
+* mono/utils/bsearch.c: BSD license.\
+\
+* mono/io-layer/wapi_glob.h, wapi_glob.c: BSD license\
+\
+Class Library code\
+==================\
+\
+These are class libraries that can be loaded by your process:\
+\
+* mcs/class/RabbitMQ.Client: dual licensed in Apache v2, and Mozilla Public License 1.1\
+\
+* mcs/class/Compat.ICSharpCode.SharpZipLib and\
+ mcs/class/ICSharpCode.SharpZipLib are GPL with class-path exception.\
+ Originates with the SharpDevelop project.\
+\
+* mcs/class/System.Core/System/TimeZoneInfo.Android.cs\
+\
+ This is a port of Apache 2.0-licensed Android code, and thus is\
+ licensed under the Apache 2.0 license\
+\
+ http://www.apache.org/licenses/LICENSE-2.0\
+\
+API Documentation\
+=================\
+\
+The API documentation is licensed under the terms of the Creative\
+Commons Attribution 4.0 International Public License\
+\
+\
+The Licenses\
+============\
+\
+ These are the licenses used in Mono, the files are located:\
+\
+### MIT X11 License\
+\
+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.\
+\
+\
+### Mozilla.MPL\
+\
+ MOZILLA PUBLIC LICENSE\
+ Version 1.1\
+\
+ ---------------\
+\
+1. Definitions.\
+\
+ 1.0.1. "Commercial Use" means distribution or otherwise making the\
+ Covered Code available to a third party.\
+\
+ 1.1. "Contributor" means each entity that creates or contributes to\
+ the creation of Modifications.\
+\
+ 1.2. "Contributor Version" means the combination of the Original\
+ Code, prior Modifications used by a Contributor, and the Modifications\
+ made by that particular Contributor.\
+\
+ 1.3. "Covered Code" means the Original Code or Modifications or the\
+ combination of the Original Code and Modifications, in each case\
+ including portions thereof.\
+\
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally\
+ accepted in the software development community for the electronic\
+ transfer of data.\
+\
+ 1.5. "Executable" means Covered Code in any form other than Source\
+ Code.\
+\
+ 1.6. "Initial Developer" means the individual or entity identified\
+ as the Initial Developer in the Source Code notice required by Exhibit\
+ A.\
+\
+ 1.7. "Larger Work" means a work which combines Covered Code or\
+ portions thereof with code not governed by the terms of this License.\
+\
+ 1.8. "License" means this document.\
+\
+ 1.8.1. "Licensable" means having the right to grant, to the maximum\
+ extent possible, whether at the time of the initial grant or\
+ subsequently acquired, any and all of the rights conveyed herein.\
+\
+ 1.9. "Modifications" means any addition to or deletion from the\
+ substance or structure of either the Original Code or any previous\
+ Modifications. When Covered Code is released as a series of files, a\
+ Modification is:\
+ A. Any addition to or deletion from the contents of a file\
+ containing Original Code or previous Modifications.\
+\
+ B. Any new file that contains any part of the Original Code or\
+ previous Modifications.\
+\
+ 1.10. "Original Code" means Source Code of computer software code\
+ which is described in the Source Code notice required by Exhibit A as\
+ Original Code, and which, at the time of its release under this\
+ License is not already Covered Code governed by this License.\
+\
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or\
+ hereafter acquired, including without limitation, method, process,\
+ and apparatus claims, in any patent Licensable by grantor.\
+\
+ 1.11. "Source Code" means the preferred form of the Covered Code for\
+ making modifications to it, including all modules it contains, plus\
+ any associated interface definition files, scripts used to control\
+ compilation and installation of an Executable, or source code\
+ differential comparisons against either the Original Code or another\
+ well known, available Covered Code of the Contributor's choice. The\
+ Source Code can be in a compressed or archival form, provided the\
+ appropriate decompression or de-archiving software is widely available\
+ for no charge.\
+\
+ 1.12. "You" (or "Your") means an individual or a legal entity\
+ exercising rights under, and complying with all of the terms of, this\
+ License or a future version of this License issued under Section 6.1.\
+ For legal entities, "You" includes any entity which controls, is\
+ controlled by, or is under common control with You. For purposes of\
+ this definition, "control" means (a) the power, direct or indirect,\
+ to cause the direction or management of such entity, whether by\
+ contract or otherwise, or (b) ownership of more than fifty percent\
+ (50%) of the outstanding shares or beneficial ownership of such\
+ entity.\
+\
+2. Source Code License.\
+\
+ 2.1. The Initial Developer Grant.\
+ The Initial Developer hereby grants You a world-wide, royalty-free,\
+ non-exclusive license, subject to third party intellectual property\
+ claims:\
+ (a) under intellectual property rights (other than patent or\
+ trademark) Licensable by Initial Developer to use, reproduce,\
+ modify, display, perform, sublicense and distribute the Original\
+ Code (or portions thereof) with or without Modifications, and/or\
+ as part of a Larger Work; and\
+\
+ (b) under Patents Claims infringed by the making, using or\
+ selling of Original Code, to make, have made, use, practice,\
+ sell, and offer for sale, and/or otherwise dispose of the\
+ Original Code (or portions thereof).\
+\
+ (c) the licenses granted in this Section 2.1(a) and (b) are\
+ effective on the date Initial Developer first distributes\
+ Original Code under the terms of this License.\
+\
+ (d) Notwithstanding Section 2.1(b) above, no patent license is\
+ granted: 1) for code that You delete from the Original Code; 2)\
+ separate from the Original Code; or 3) for infringements caused\
+ by: i) the modification of the Original Code or ii) the\
+ combination of the Original Code with other software or devices.\
+\
+ 2.2. Contributor Grant.\
+ Subject to third party intellectual property claims, each Contributor\
+ hereby grants You a world-wide, royalty-free, non-exclusive license\
+\
+ (a) under intellectual property rights (other than patent or\
+ trademark) Licensable by Contributor, to use, reproduce, modify,\
+ display, perform, sublicense and distribute the Modifications\
+ created by such Contributor (or portions thereof) either on an\
+ unmodified basis, with other Modifications, as Covered Code\
+ and/or as part of a Larger Work; and\
+\
+ (b) under Patent Claims infringed by the making, using, or\
+ selling of Modifications made by that Contributor either alone\
+ and/or in combination with its Contributor Version (or portions\
+ of such combination), to make, use, sell, offer for sale, have\
+ made, and/or otherwise dispose of: 1) Modifications made by that\
+ Contributor (or portions thereof); and 2) the combination of\
+ Modifications made by that Contributor with its Contributor\
+ Version (or portions of such combination).\
+\
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are\
+ effective on the date Contributor first makes Commercial Use of\
+ the Covered Code.\
+\
+ (d) Notwithstanding Section 2.2(b) above, no patent license is\
+ granted: 1) for any code that Contributor has deleted from the\
+ Contributor Version; 2) separate from the Contributor Version;\
+ 3) for infringements caused by: i) third party modifications of\
+ Contributor Version or ii) the combination of Modifications made\
+ by that Contributor with other software (except as part of the\
+ Contributor Version) or other devices; or 4) under Patent Claims\
+ infringed by Covered Code in the absence of Modifications made by\
+ that Contributor.\
+\
+3. Distribution Obligations.\
+\
+ 3.1. Application of License.\
+ The Modifications which You create or to which You contribute are\
+ governed by the terms of this License, including without limitation\
+ Section 2.2. The Source Code version of Covered Code may be\
+ distributed only under the terms of this License or a future version\
+ of this License released under Section 6.1, and You must include a\
+ copy of this License with every copy of the Source Code You\
+ distribute. You may not offer or impose any terms on any Source Code\
+ version that alters or restricts the applicable version of this\
+ License or the recipients' rights hereunder. However, You may include\
+ an additional document offering the additional rights described in\
+ Section 3.5.\
+\
+ 3.2. Availability of Source Code.\
+ Any Modification which You create or to which You contribute must be\
+ made available in Source Code form under the terms of this License\
+ either on the same media as an Executable version or via an accepted\
+ Electronic Distribution Mechanism to anyone to whom you made an\
+ Executable version available; and if made available via Electronic\
+ Distribution Mechanism, must remain available for at least twelve (12)\
+ months after the date it initially became available, or at least six\
+ (6) months after a subsequent version of that particular Modification\
+ has been made available to such recipients. You are responsible for\
+ ensuring that the Source Code version remains available even if the\
+ Electronic Distribution Mechanism is maintained by a third party.\
+\
+ 3.3. Description of Modifications.\
+ You must cause all Covered Code to which You contribute to contain a\
+ file documenting the changes You made to create that Covered Code and\
+ the date of any change. You must include a prominent statement that\
+ the Modification is derived, directly or indirectly, from Original\
+ Code provided by the Initial Developer and including the name of the\
+ Initial Developer in (a) the Source Code, and (b) in any notice in an\
+ Executable version or related documentation in which You describe the\
+ origin or ownership of the Covered Code.\
+\
+ 3.4. Intellectual Property Matters\
+ (a) Third Party Claims.\
+ If Contributor has knowledge that a license under a third party's\
+ intellectual property rights is required to exercise the rights\
+ granted by such Contributor under Sections 2.1 or 2.2,\
+ Contributor must include a text file with the Source Code\
+ distribution titled "LEGAL" which describes the claim and the\
+ party making the claim in sufficient detail that a recipient will\
+ know whom to contact. If Contributor obtains such knowledge after\
+ the Modification is made available as described in Section 3.2,\
+ Contributor shall promptly modify the LEGAL file in all copies\
+ Contributor makes available thereafter and shall take other steps\
+ (such as notifying appropriate mailing lists or newsgroups)\
+ reasonably calculated to inform those who received the Covered\
+ Code that new knowledge has been obtained.\
+\
+ (b) Contributor APIs.\
+ If Contributor's Modifications include an application programming\
+ interface and Contributor has knowledge of patent licenses which\
+ are reasonably necessary to implement that API, Contributor must\
+ also include this information in the LEGAL file.\
+\
+ (c) Representations.\
+ Contributor represents that, except as disclosed pursuant to\
+ Section 3.4(a) above, Contributor believes that Contributor's\
+ Modifications are Contributor's original creation(s) and/or\
+ Contributor has sufficient rights to grant the rights conveyed by\
+ this License.\
+\
+ 3.5. Required Notices.\
+ You must duplicate the notice in Exhibit A in each file of the Source\
+ Code. If it is not possible to put such notice in a particular Source\
+ Code file due to its structure, then You must include such notice in a\
+ location (such as a relevant directory) where a user would be likely\
+ to look for such a notice. If You created one or more Modification(s)\
+ You may add your name as a Contributor to the notice described in\
+ Exhibit A. You must also duplicate this License in any documentation\
+ for the Source Code where You describe recipients' rights or ownership\
+ rights relating to Covered Code. You may choose to offer, and to\
+ charge a fee for, warranty, support, indemnity or liability\
+ obligations to one or more recipients of Covered Code. However, You\
+ may do so only on Your own behalf, and not on behalf of the Initial\
+ Developer or any Contributor. You must make it absolutely clear than\
+ any such warranty, support, indemnity or liability obligation is\
+ offered by You alone, and You hereby agree to indemnify the Initial\
+ Developer and every Contributor for any liability incurred by the\
+ Initial Developer or such Contributor as a result of warranty,\
+ support, indemnity or liability terms You offer.\
+\
+ 3.6. Distribution of Executable Versions.\
+ You may distribute Covered Code in Executable form only if the\
+ requirements of Section 3.1-3.5 have been met for that Covered Code,\
+ and if You include a notice stating that the Source Code version of\
+ the Covered Code is available under the terms of this License,\
+ including a description of how and where You have fulfilled the\
+ obligations of Section 3.2. The notice must be conspicuously included\
+ in any notice in an Executable version, related documentation or\
+ collateral in which You describe recipients' rights relating to the\
+ Covered Code. You may distribute the Executable version of Covered\
+ Code or ownership rights under a license of Your choice, which may\
+ contain terms different from this License, provided that You are in\
+ compliance with the terms of this License and that the license for the\
+ Executable version does not attempt to limit or alter the recipient's\
+ rights in the Source Code version from the rights set forth in this\
+ License. If You distribute the Executable version under a different\
+ license You must make it absolutely clear that any terms which differ\
+ from this License are offered by You alone, not by the Initial\
+ Developer or any Contributor. You hereby agree to indemnify the\
+ Initial Developer and every Contributor for any liability incurred by\
+ the Initial Developer or such Contributor as a result of any such\
+ terms You offer.\
+\
+ 3.7. Larger Works.\
+ You may create a Larger Work by combining Covered Code with other code\
+ not governed by the terms of this License and distribute the Larger\
+ Work as a single product. In such a case, You must make sure the\
+ requirements of this License are fulfilled for the Covered Code.\
+\
+4. Inability to Comply Due to Statute or Regulation.\
+\
+ If it is impossible for You to comply with any of the terms of this\
+ License with respect to some or all of the Covered Code due to\
+ statute, judicial order, or regulation then You must: (a) comply with\
+ the terms of this License to the maximum extent possible; and (b)\
+ describe the limitations and the code they affect. Such description\
+ must be included in the LEGAL file described in Section 3.4 and must\
+ be included with all distributions of the Source Code. Except to the\
+ extent prohibited by statute or regulation, such description must be\
+ sufficiently detailed for a recipient of ordinary skill to be able to\
+ understand it.\
+\
+5. Application of this License.\
+\
+ This License applies to code to which the Initial Developer has\
+ attached the notice in Exhibit A and to related Covered Code.\
+\
+6. Versions of the License.\
+\
+ 6.1. New Versions.\
+ Netscape Communications Corporation ("Netscape") may publish revised\
+ and/or new versions of the License from time to time. Each version\
+ will be given a distinguishing version number.\
+\
+ 6.2. Effect of New Versions.\
+ Once Covered Code has been published under a particular version of the\
+ License, You may always continue to use it under the terms of that\
+ version. You may also choose to use such Covered Code under the terms\
+ of any subsequent version of the License published by Netscape. No one\
+ other than Netscape has the right to modify the terms applicable to\
+ Covered Code created under this License.\
+\
+ 6.3. Derivative Works.\
+ If You create or use a modified version of this License (which you may\
+ only do in order to apply it to code which is not already Covered Code\
+ governed by this License), You must (a) rename Your license so that\
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",\
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your\
+ license (except to note that your license differs from this License)\
+ and (b) otherwise make it clear that Your version of the license\
+ contains terms which differ from the Mozilla Public License and\
+ Netscape Public License. (Filling in the name of the Initial\
+ Developer, Original Code or Contributor in the notice described in\
+ Exhibit A shall not of themselves be deemed to be modifications of\
+ this License.)\
+\
+7. DISCLAIMER OF WARRANTY.\
+\
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,\
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,\
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF\
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.\
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE\
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,\
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE\
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER\
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF\
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.\
+\
+8. TERMINATION.\
+\
+ 8.1. This License and the rights granted hereunder will terminate\
+ automatically if You fail to comply with terms herein and fail to cure\
+ such breach within 30 days of becoming aware of the breach. All\
+ sublicenses to the Covered Code which are properly granted shall\
+ survive any termination of this License. Provisions which, by their\
+ nature, must remain in effect beyond the termination of this License\
+ shall survive.\
+\
+ 8.2. If You initiate litigation by asserting a patent infringement\
+ claim (excluding declatory judgment actions) against Initial Developer\
+ or a Contributor (the Initial Developer or Contributor against whom\
+ You file such action is referred to as "Participant") alleging that:\
+\
+ (a) such Participant's Contributor Version directly or indirectly\
+ infringes any patent, then any and all rights granted by such\
+ Participant to You under Sections 2.1 and/or 2.2 of this License\
+ shall, upon 60 days notice from Participant terminate prospectively,\
+ unless if within 60 days after receipt of notice You either: (i)\
+ agree in writing to pay Participant a mutually agreeable reasonable\
+ royalty for Your past and future use of Modifications made by such\
+ Participant, or (ii) withdraw Your litigation claim with respect to\
+ the Contributor Version against such Participant. If within 60 days\
+ of notice, a reasonable royalty and payment arrangement are not\
+ mutually agreed upon in writing by the parties or the litigation claim\
+ is not withdrawn, the rights granted by Participant to You under\
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of\
+ the 60 day notice period specified above.\
+\
+ (b) any software, hardware, or device, other than such Participant's\
+ Contributor Version, directly or indirectly infringes any patent, then\
+ any rights granted to You by such Participant under Sections 2.1(b)\
+ and 2.2(b) are revoked effective as of the date You first made, used,\
+ sold, distributed, or had made, Modifications made by that\
+ Participant.\
+\
+ 8.3. If You assert a patent infringement claim against Participant\
+ alleging that such Participant's Contributor Version directly or\
+ indirectly infringes any patent where such claim is resolved (such as\
+ by license or settlement) prior to the initiation of patent\
+ infringement litigation, then the reasonable value of the licenses\
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken\
+ into account in determining the amount or value of any payment or\
+ license.\
+\
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,\
+ all end user license agreements (excluding distributors and resellers)\
+ which have been validly granted by You or any distributor hereunder\
+ prior to termination shall survive termination.\
+\
+9. LIMITATION OF LIABILITY.\
+\
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT\
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL\
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,\
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR\
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY\
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,\
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER\
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN\
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF\
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY\
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW\
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE\
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO\
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.\
+\
+10. U.S. GOVERNMENT END USERS.\
+\
+ The Covered Code is a "commercial item," as that term is defined in\
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer\
+ software" and "commercial computer software documentation," as such\
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48\
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),\
+ all U.S. Government End Users acquire Covered Code with only those\
+ rights set forth herein.\
+\
+11. MISCELLANEOUS.\
+\
+ This License represents the complete agreement concerning subject\
+ matter hereof. If any provision of this License is held to be\
+ unenforceable, such provision shall be reformed only to the extent\
+ necessary to make it enforceable. This License shall be governed by\
+ California law provisions (except to the extent applicable law, if\
+ any, provides otherwise), excluding its conflict-of-law provisions.\
+ With respect to disputes in which at least one party is a citizen of,\
+ or an entity chartered or registered to do business in the United\
+ States of America, any litigation relating to this License shall be\
+ subject to the jurisdiction of the Federal Courts of the Northern\
+ District of California, with venue lying in Santa Clara County,\
+ California, with the losing party responsible for costs, including\
+ without limitation, court costs and reasonable attorneys' fees and\
+ expenses. The application of the United Nations Convention on\
+ Contracts for the International Sale of Goods is expressly excluded.\
+ Any law or regulation which provides that the language of a contract\
+ shall be construed against the drafter shall not apply to this\
+ License.\
+\
+12. RESPONSIBILITY FOR CLAIMS.\
+\
+ As between Initial Developer and the Contributors, each party is\
+ responsible for claims and damages arising, directly or indirectly,\
+ out of its utilization of rights under this License and You agree to\
+ work with Initial Developer and Contributors to distribute such\
+ responsibility on an equitable basis. Nothing herein is intended or\
+ shall be deemed to constitute any admission of liability.\
+\
+13. MULTIPLE-LICENSED CODE.\
+\
+ Initial Developer may designate portions of the Covered Code as\
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial\
+ Developer permits you to utilize portions of the Covered Code under\
+ Your choice of the NPL or the alternative licenses, if any, specified\
+ by the Initial Developer in the file described in Exhibit A.\
+\
+EXHIBIT A -Mozilla Public License.\
+\
+ ``The contents of this file are subject to the Mozilla Public License\
+ Version 1.1 (the "License"); you may not use this file except in\
+ compliance with the License. You may obtain a copy of the License at\
+ http://www.mozilla.org/MPL/\
+\
+ Software distributed under the License is distributed on an "AS IS"\
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\
+ License for the specific language governing rights and limitations\
+ under the License.\
+\
+ The Original Code is ______________________________________.\
+\
+ The Initial Developer of the Original Code is ________________________.\
+ Portions created by ______________________ are Copyright (C) ______\
+ _______________________. All Rights Reserved.\
+\
+ Contributor(s): ______________________________________.\
+\
+ Alternatively, the contents of this file may be used under the terms\
+ of the _____ license (the "[___] License"), in which case the\
+ provisions of [______] License are applicable instead of those\
+ above. If you wish to allow use of your version of this file only\
+ under the terms of the [____] License and not to allow others to use\
+ your version of this file under the MPL, indicate your decision by\
+ deleting the provisions above and replace them with the notice and\
+ other provisions required by the [___] License. If you do not delete\
+ the provisions above, a recipient may use your version of this file\
+ under either the MPL or the [___] License."\
+\
+ [NOTE: The text of this Exhibit A may differ slightly from the text of\
+ the notices in the Source Code files of the Original Code. You should\
+ use the text of this Exhibit A rather than the text found in the\
+ Original Code Source Code for Your Modifications.]\
+\
+### Microsoft Public License\
+\
+Microsoft Permissive License (Ms-PL)\
+ \
+ This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.\
+ \
+1. Definitions\
+\
+ The terms \uc0\u147 reproduce,\u148 \u147 reproduction,\u148 \u147 derivative works,\u148 and \u147 distribution\u148 have the same meaning here as under U.S. copyright law.\
+ A \uc0\u147 contribution\u148 is the original software, or any additions or changes to the software.\
+ A \uc0\u147 contributor\u148 is any person that distributes its contribution under this license.\
+ \uc0\u147 Licensed patents\u148 are a contributor\u146 s patent claims that read directly on its contribution.\
+ \
+2. Grant of Rights\
+\
+ (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\
+ (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\
+ \
+3. Conditions and Limitations\
+\
+ (A) No Trademark License- This license does not grant you rights to use any contributors\uc0\u146 name, logo, or trademarks.\
+ (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\
+ (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\
+ (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\
+ (E) The software is licensed \uc0\u147 as-is.\u148 You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\
+ (F) If you distribute the software or derivative works with programs you develop, you agree to indemnify, defend, and hold harmless all contributors from any claims, including attorneys\uc0\u146 fees, related to the distribution or use of your programs. For clarity, you have no such obligations to a contributor for any claims based solely on the unmodified contributions of that contributor.\
+ (G) If you make any additions or changes to the original software, you may only distribute them under a new namespace. In addition, you will clearly identify your changes or additions as your own.\
+\
+### Infozip BSD\
+\
+This is version 2009-Jan-02 of the Info-ZIP license. The definitive\
+version of this document should be available at\
+ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a\
+copy at http://www.info-zip.org/pub/infozip/license.html.\
+\
+Copyright (c) 1990-2009 Info-ZIP. All rights reserved.\
+\
+For the purposes of this copyright and license, "Info-ZIP" is defined\
+as the following set of individuals: Mark Adler, John Bush, Karl\
+Davis, Harald Denker, Jean-Michel Dubois, Jean-loup Gailly, Hunter\
+Goatley, Ed Gordon, Ian Gorman, Chris Herborth, Dirk Haase, Greg\
+Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David\
+Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve\
+P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\
+Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\
+Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\
+Rich Wales, Mike White.\
+\
+This software is provided "as is," without warranty of any kind,\
+express or implied. In no event shall Info-ZIP or its contributors be\
+held liable for any direct, indirect, incidental, special or\
+consequential damages arising out of the use of or inability to use\
+this software.\
+\
+Permission is granted to anyone to use this software for any purpose,\
+including commercial applications, and to alter it and redistribute it\
+freely, subject to the above disclaimer and the following\
+restrictions:\
+\
+Redistributions of source code (in whole or in part) must retain the\
+above copyright notice, definition, disclaimer, and this list of\
+conditions.\
+\
+Redistributions in binary form (compiled executables and libraries)\
+must reproduce the above copyright notice, definition, disclaimer, and\
+this list of conditions in documentation and/or other materials\
+provided with the distribution. Additional documentation is not needed\
+for executables where a command line license option provides these and\
+a note regarding this option is in the executable's startup\
+banner. The sole exception to this condition is redistribution of a\
+standard UnZipSFX binary (including SFXWiz) as part of a\
+self-extracting archive; that is permitted without inclusion of this\
+license, as long as the normal SFX banner has not been removed from\
+the binary or disabled.\
+\
+Altered versions--including, but not limited to, ports to new\
+operating systems, existing ports with new graphical interfaces,\
+versions with modified or added functionality, and dynamic, shared, or\
+static library versions not from Info-ZIP--must be plainly marked as\
+such and must not be misrepresented as being the original source or,\
+if binaries, compiled from the original source. Such altered versions\
+also must not be misrepresented as being Info-ZIP releases--including,\
+but not limited to, labeling of the altered versions with the names\
+"Info-ZIP" (or any variation thereof, including, but not limited to,\
+different capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without\
+the explicit permission of Info-ZIP. Such altered versions are further\
+prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\
+e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\
+will provide support for the altered versions.\
+\
+Info-ZIP retains the right to use the names "Info-ZIP," "Zip,"\
+"UnZip," "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip"\
+for its own source and binary releases.\
+\
+### License Creative Commons 2.5\
+\
+// Copyright 2006 James Newton-King\
+// http://www.newtonsoft.com\
+//\
+// This work is licensed under the Creative Commons Attribution 2.5 License\
+// http://creativecommons.org/licenses/by/2.5/\
+//\
+// You are free:\
+// * to copy, distribute, display, and perform the work\
+// * to make derivative works\
+// * to make commercial use of the work\
+//\
+// Under the following conditions:\
+// * For any reuse or distribution, you must make clear to others the license terms of this work.\
+// * Any of these conditions can be waived if you get permission from the copyright holder.\
+\
+From: james.newtonking@gmail.com [mailto:james.newtonking@gmail.com] On Behalf Of James Newton-King\
+Sent: Tuesday, June 05, 2007 6:36 AM\
+To: Konstantin Triger\
+Subject: Re: Support request by Konstantin Triger for Json.NET\
+\
+Hey Kosta\
+\
+I think it would be awesome to use Json.NET in Mono for System.Web.Extensions.\
+\
+The CC license has the following clause: Any of the above conditions can be waived if you get permission from the copyright holder.\
+\
+I can waive that statement for you and Mono. Would that be acceptable?\
+\
+\
+Regards,\
+James\
+\
+### Creative Commons Attribution 4.0 International Public License\
+\
+Attribution 4.0 International\
+\
+=======================================================================\
+\
+Creative Commons Corporation ("Creative Commons") is not a law firm and\
+does not provide legal services or legal advice. Distribution of\
+Creative Commons public licenses does not create a lawyer-client or\
+other relationship. Creative Commons makes its licenses and related\
+information available on an "as-is" basis. Creative Commons gives no\
+warranties regarding its licenses, any material licensed under their\
+terms and conditions, or any related information. Creative Commons\
+disclaims all liability for damages resulting from their use to the\
+fullest extent possible.\
+\
+Using Creative Commons Public Licenses\
+\
+Creative Commons public licenses provide a standard set of terms and\
+conditions that creators and other rights holders may use to share\
+original works of authorship and other material subject to copyright\
+and certain other rights specified in the public license below. The\
+following considerations are for informational purposes only, are not\
+exhaustive, and do not form part of our licenses.\
+\
+ Considerations for licensors: Our public licenses are\
+ intended for use by those authorized to give the public\
+ permission to use material in ways otherwise restricted by\
+ copyright and certain other rights. Our licenses are\
+ irrevocable. Licensors should read and understand the terms\
+ and conditions of the license they choose before applying it.\
+ Licensors should also secure all rights necessary before\
+ applying our licenses so that the public can reuse the\
+ material as expected. Licensors should clearly mark any\
+ material not subject to the license. This includes other CC-\
+ licensed material, or material used under an exception or\
+ limitation to copyright. More considerations for licensors:\
+ wiki.creativecommons.org/Considerations_for_licensors\
+\
+ Considerations for the public: By using one of our public\
+ licenses, a licensor grants the public permission to use the\
+ licensed material under specified terms and conditions. If\
+ the licensor's permission is not necessary for any reason--for\
+ example, because of any applicable exception or limitation to\
+ copyright--then that use is not regulated by the license. Our\
+ licenses grant only permissions under copyright and certain\
+ other rights that a licensor has authority to grant. Use of\
+ the licensed material may still be restricted for other\
+ reasons, including because others have copyright or other\
+ rights in the material. A licensor may make special requests,\
+ such as asking that all changes be marked or described.\
+ Although not required by our licenses, you are encouraged to\
+ respect those requests where reasonable. More_considerations\
+ for the public: \
+ wiki.creativecommons.org/Considerations_for_licensees\
+\
+=======================================================================\
+\
+Creative Commons Attribution 4.0 International Public License\
+\
+By exercising the Licensed Rights (defined below), You accept and agree\
+to be bound by the terms and conditions of this Creative Commons\
+Attribution 4.0 International Public License ("Public License"). To the\
+extent this Public License may be interpreted as a contract, You are\
+granted the Licensed Rights in consideration of Your acceptance of\
+these terms and conditions, and the Licensor grants You such rights in\
+consideration of benefits the Licensor receives from making the\
+Licensed Material available under these terms and conditions.\
+\
+\
+Section 1 -- Definitions.\
+\
+ a. Adapted Material means material subject to Copyright and Similar\
+ Rights that is derived from or based upon the Licensed Material\
+ and in which the Licensed Material is translated, altered,\
+ arranged, transformed, or otherwise modified in a manner requiring\
+ permission under the Copyright and Similar Rights held by the\
+ Licensor. For purposes of this Public License, where the Licensed\
+ Material is a musical work, performance, or sound recording,\
+ Adapted Material is always produced where the Licensed Material is\
+ synched in timed relation with a moving image.\
+\
+ b. Adapter's License means the license You apply to Your Copyright\
+ and Similar Rights in Your contributions to Adapted Material in\
+ accordance with the terms and conditions of this Public License.\
+\
+ c. Copyright and Similar Rights means copyright and/or similar rights\
+ closely related to copyright including, without limitation,\
+ performance, broadcast, sound recording, and Sui Generis Database\
+ Rights, without regard to how the rights are labeled or\
+ categorized. For purposes of this Public License, the rights\
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar\
+ Rights.\
+\
+ d. Effective Technological Measures means those measures that, in the\
+ absence of proper authority, may not be circumvented under laws\
+ fulfilling obligations under Article 11 of the WIPO Copyright\
+ Treaty adopted on December 20, 1996, and/or similar international\
+ agreements.\
+\
+ e. Exceptions and Limitations means fair use, fair dealing, and/or\
+ any other exception or limitation to Copyright and Similar Rights\
+ that applies to Your use of the Licensed Material.\
+\
+ f. Licensed Material means the artistic or literary work, database,\
+ or other material to which the Licensor applied this Public\
+ License.\
+\
+ g. Licensed Rights means the rights granted to You subject to the\
+ terms and conditions of this Public License, which are limited to\
+ all Copyright and Similar Rights that apply to Your use of the\
+ Licensed Material and that the Licensor has authority to license.\
+\
+ h. Licensor means the individual(s) or entity(ies) granting rights\
+ under this Public License.\
+\
+ i. Share means to provide material to the public by any means or\
+ process that requires permission under the Licensed Rights, such\
+ as reproduction, public display, public performance, distribution,\
+ dissemination, communication, or importation, and to make material\
+ available to the public including in ways that members of the\
+ public may access the material from a place and at a time\
+ individually chosen by them.\
+\
+ j. Sui Generis Database Rights means rights other than copyright\
+ resulting from Directive 96/9/EC of the European Parliament and of\
+ the Council of 11 March 1996 on the legal protection of databases,\
+ as amended and/or succeeded, as well as other essentially\
+ equivalent rights anywhere in the world.\
+\
+ k. You means the individual or entity exercising the Licensed Rights\
+ under this Public License. Your has a corresponding meaning.\
+\
+\
+Section 2 -- Scope.\
+\
+ a. License grant.\
+\
+ 1. Subject to the terms and conditions of this Public License,\
+ the Licensor hereby grants You a worldwide, royalty-free,\
+ non-sublicensable, non-exclusive, irrevocable license to\
+ exercise the Licensed Rights in the Licensed Material to:\
+\
+ a. reproduce and Share the Licensed Material, in whole or\
+ in part; and\
+\
+ b. produce, reproduce, and Share Adapted Material.\
+\
+ 2. Exceptions and Limitations. For the avoidance of doubt, where\
+ Exceptions and Limitations apply to Your use, this Public\
+ License does not apply, and You do not need to comply with\
+ its terms and conditions.\
+\
+ 3. Term. The term of this Public License is specified in Section\
+ 6(a).\
+\
+ 4. Media and formats; technical modifications allowed. The\
+ Licensor authorizes You to exercise the Licensed Rights in\
+ all media and formats whether now known or hereafter created,\
+ and to make technical modifications necessary to do so. The\
+ Licensor waives and/or agrees not to assert any right or\
+ authority to forbid You from making technical modifications\
+ necessary to exercise the Licensed Rights, including\
+ technical modifications necessary to circumvent Effective\
+ Technological Measures. For purposes of this Public License,\
+ simply making modifications authorized by this Section 2(a)\
+ (4) never produces Adapted Material.\
+\
+ 5. Downstream recipients.\
+\
+ a. Offer from the Licensor -- Licensed Material. Every\
+ recipient of the Licensed Material automatically\
+ receives an offer from the Licensor to exercise the\
+ Licensed Rights under the terms and conditions of this\
+ Public License.\
+\
+ b. No downstream restrictions. You may not offer or impose\
+ any additional or different terms or conditions on, or\
+ apply any Effective Technological Measures to, the\
+ Licensed Material if doing so restricts exercise of the\
+ Licensed Rights by any recipient of the Licensed\
+ Material.\
+\
+ 6. No endorsement. Nothing in this Public License constitutes or\
+ may be construed as permission to assert or imply that You\
+ are, or that Your use of the Licensed Material is, connected\
+ with, or sponsored, endorsed, or granted official status by,\
+ the Licensor or others designated to receive attribution as\
+ provided in Section 3(a)(1)(A)(i).\
+\
+ b. Other rights.\
+\
+ 1. Moral rights, such as the right of integrity, are not\
+ licensed under this Public License, nor are publicity,\
+ privacy, and/or other similar personality rights; however, to\
+ the extent possible, the Licensor waives and/or agrees not to\
+ assert any such rights held by the Licensor to the limited\
+ extent necessary to allow You to exercise the Licensed\
+ Rights, but not otherwise.\
+\
+ 2. Patent and trademark rights are not licensed under this\
+ Public License.\
+\
+ 3. To the extent possible, the Licensor waives any right to\
+ collect royalties from You for the exercise of the Licensed\
+ Rights, whether directly or through a collecting society\
+ under any voluntary or waivable statutory or compulsory\
+ licensing scheme. In all other cases the Licensor expressly\
+ reserves any right to collect such royalties.\
+\
+\
+Section 3 -- License Conditions.\
+\
+Your exercise of the Licensed Rights is expressly made subject to the\
+following conditions.\
+\
+ a. Attribution.\
+\
+ 1. If You Share the Licensed Material (including in modified\
+ form), You must:\
+\
+ a. retain the following if it is supplied by the Licensor\
+ with the Licensed Material:\
+\
+ i. identification of the creator(s) of the Licensed\
+ Material and any others designated to receive\
+ attribution, in any reasonable manner requested by\
+ the Licensor (including by pseudonym if\
+ designated);\
+\
+ ii. a copyright notice;\
+\
+ iii. a notice that refers to this Public License;\
+\
+ iv. a notice that refers to the disclaimer of\
+ warranties;\
+\
+ v. a URI or hyperlink to the Licensed Material to the\
+ extent reasonably practicable;\
+\
+ b. indicate if You modified the Licensed Material and\
+ retain an indication of any previous modifications; and\
+\
+ c. indicate the Licensed Material is licensed under this\
+ Public License, and include the text of, or the URI or\
+ hyperlink to, this Public License.\
+\
+ 2. You may satisfy the conditions in Section 3(a)(1) in any\
+ reasonable manner based on the medium, means, and context in\
+ which You Share the Licensed Material. For example, it may be\
+ reasonable to satisfy the conditions by providing a URI or\
+ hyperlink to a resource that includes the required\
+ information.\
+\
+ 3. If requested by the Licensor, You must remove any of the\
+ information required by Section 3(a)(1)(A) to the extent\
+ reasonably practicable.\
+\
+ 4. If You Share Adapted Material You produce, the Adapter's\
+ License You apply must not prevent recipients of the Adapted\
+ Material from complying with this Public License.\
+\
+\
+Section 4 -- Sui Generis Database Rights.\
+\
+Where the Licensed Rights include Sui Generis Database Rights that\
+apply to Your use of the Licensed Material:\
+\
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right\
+ to extract, reuse, reproduce, and Share all or a substantial\
+ portion of the contents of the database;\
+\
+ b. if You include all or a substantial portion of the database\
+ contents in a database in which You have Sui Generis Database\
+ Rights, then the database in which You have Sui Generis Database\
+ Rights (but not its individual contents) is Adapted Material; and\
+\
+ c. You must comply with the conditions in Section 3(a) if You Share\
+ all or a substantial portion of the contents of the database.\
+\
+For the avoidance of doubt, this Section 4 supplements and does not\
+replace Your obligations under this Public License where the Licensed\
+Rights include other Copyright and Similar Rights.\
+\
+\
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.\
+\
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\
+\
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\
+\
+ c. The disclaimer of warranties and limitation of liability provided\
+ above shall be interpreted in a manner that, to the extent\
+ possible, most closely approximates an absolute disclaimer and\
+ waiver of all liability.\
+\
+\
+Section 6 -- Term and Termination.\
+\
+ a. This Public License applies for the term of the Copyright and\
+ Similar Rights licensed here. However, if You fail to comply with\
+ this Public License, then Your rights under this Public License\
+ terminate automatically.\
+\
+ b. Where Your right to use the Licensed Material has terminated under\
+ Section 6(a), it reinstates:\
+\
+ 1. automatically as of the date the violation is cured, provided\
+ it is cured within 30 days of Your discovery of the\
+ violation; or\
+\
+ 2. upon express reinstatement by the Licensor.\
+\
+ For the avoidance of doubt, this Section 6(b) does not affect any\
+ right the Licensor may have to seek remedies for Your violations\
+ of this Public License.\
+\
+ c. For the avoidance of doubt, the Licensor may also offer the\
+ Licensed Material under separate terms or conditions or stop\
+ distributing the Licensed Material at any time; however, doing so\
+ will not terminate this Public License.\
+\
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\
+ License.\
+\
+\
+Section 7 -- Other Terms and Conditions.\
+\
+ a. The Licensor shall not be bound by any additional or different\
+ terms or conditions communicated by You unless expressly agreed.\
+\
+ b. Any arrangements, understandings, or agreements regarding the\
+ Licensed Material not stated herein are separate from and\
+ independent of the terms and conditions of this Public License.\
+\
+\
+Section 8 -- Interpretation.\
+\
+ a. For the avoidance of doubt, this Public License does not, and\
+ shall not be interpreted to, reduce, limit, restrict, or impose\
+ conditions on any use of the Licensed Material that could lawfully\
+ be made without permission under this Public License.\
+\
+ b. To the extent possible, if any provision of this Public License is\
+ deemed unenforceable, it shall be automatically reformed to the\
+ minimum extent necessary to make it enforceable. If the provision\
+ cannot be reformed, it shall be severed from this Public License\
+ without affecting the enforceability of the remaining terms and\
+ conditions.\
+\
+ c. No term or condition of this Public License will be waived and no\
+ failure to comply consented to unless expressly agreed to by the\
+ Licensor.\
+\
+ d. Nothing in this Public License constitutes or may be interpreted\
+ as a limitation upon, or waiver of, any privileges and immunities\
+ that apply to the Licensor or You, including from the legal\
+ processes of any jurisdiction or authority.\
+\
+\
+=======================================================================\
+\
+Creative Commons is not a party to its public\
+licenses. Notwithstanding, Creative Commons may elect to apply one of\
+its public licenses to material it publishes and in those instances\
+will be considered the \'93Licensor.\'94 The text of the Creative Commons\
+public licenses is dedicated to the public domain under the CC0 Public\
+Domain Dedication. Except for the limited purpose of indicating that\
+material is shared under a Creative Commons public license or as\
+otherwise permitted by the Creative Commons policies published at\
+creativecommons.org/policies, Creative Commons does not authorize the\
+use of the trademark "Creative Commons" or any other trademark or logo\
+of Creative Commons without its prior written consent including,\
+without limitation, in connection with any unauthorized modifications\
+to any of its public licenses or any other arrangements,\
+understandings, or agreements concerning use of licensed material. For\
+the avoidance of doubt, this paragraph does not form part of the\
+public licenses.\
+\
+Creative Commons may be contacted at creativecommons.org.\
+\
+### GPL version 2\
+\
+ GNU GENERAL PUBLIC LICENSE\
+ Version 2, June 1991\
+\
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\
+ Everyone is permitted to copy and distribute verbatim copies\
+ of this license document, but changing it is not allowed.\
+\
+ Preamble\
+\
+ The licenses for most software are designed to take away your\
+freedom to share and change it. By contrast, the GNU General Public\
+License is intended to guarantee your freedom to share and change free\
+software--to make sure the software is free for all its users. This\
+General Public License applies to most of the Free Software\
+Foundation's software and to any other program whose authors commit to\
+using it. (Some other Free Software Foundation software is covered by\
+the GNU Library General Public License instead.) You can apply it to\
+your programs, too.\
+\
+ When we speak of free software, we are referring to freedom, not\
+price. Our General Public Licenses are designed to make sure that you\
+have the freedom to distribute copies of free software (and charge for\
+this service if you wish), that you receive source code or can get it\
+if you want it, that you can change the software or use pieces of it\
+in new free programs; and that you know you can do these things.\
+\
+ To protect your rights, we need to make restrictions that forbid\
+anyone to deny you these rights or to ask you to surrender the rights.\
+These restrictions translate to certain responsibilities for you if you\
+distribute copies of the software, or if you modify it.\
+\
+ For example, if you distribute copies of such a program, whether\
+gratis or for a fee, you must give the recipients all the rights that\
+you have. You must make sure that they, too, receive or can get the\
+source code. And you must show them these terms so they know their\
+rights.\
+\
+ We protect your rights with two steps: (1) copyright the software, and\
+(2) offer you this license which gives you legal permission to copy,\
+distribute and/or modify the software.\
+\
+ Also, for each author's protection and ours, we want to make certain\
+that everyone understands that there is no warranty for this free\
+software. If the software is modified by someone else and passed on, we\
+want its recipients to know that what they have is not the original, so\
+that any problems introduced by others will not reflect on the original\
+authors' reputations.\
+\
+ Finally, any free program is threatened constantly by software\
+patents. We wish to avoid the danger that redistributors of a free\
+program will individually obtain patent licenses, in effect making the\
+program proprietary. To prevent this, we have made it clear that any\
+patent must be licensed for everyone's free use or not licensed at all.\
+\
+ The precise terms and conditions for copying, distribution and\
+modification follow.\
+\page \
+ GNU GENERAL PUBLIC LICENSE\
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\
+\
+ 0. This License applies to any program or other work which contains\
+a notice placed by the copyright holder saying it may be distributed\
+under the terms of this General Public License. The "Program", below,\
+refers to any such program or work, and a "work based on the Program"\
+means either the Program or any derivative work under copyright law:\
+that is to say, a work containing the Program or a portion of it,\
+either verbatim or with modifications and/or translated into another\
+language. (Hereinafter, translation is included without limitation in\
+the term "modification".) Each licensee is addressed as "you".\
+\
+Activities other than copying, distribution and modification are not\
+covered by this License; they are outside its scope. The act of\
+running the Program is not restricted, and the output from the Program\
+is covered only if its contents constitute a work based on the\
+Program (independent of having been made by running the Program).\
+Whether that is true depends on what the Program does.\
+\
+ 1. You may copy and distribute verbatim copies of the Program's\
+source code as you receive it, in any medium, provided that you\
+conspicuously and appropriately publish on each copy an appropriate\
+copyright notice and disclaimer of warranty; keep intact all the\
+notices that refer to this License and to the absence of any warranty;\
+and give any other recipients of the Program a copy of this License\
+along with the Program.\
+\
+You may charge a fee for the physical act of transferring a copy, and\
+you may at your option offer warranty protection in exchange for a fee.\
+\
+ 2. You may modify your copy or copies of the Program or any portion\
+of it, thus forming a work based on the Program, and copy and\
+distribute such modifications or work under the terms of Section 1\
+above, provided that you also meet all of these conditions:\
+\
+ a) You must cause the modified files to carry prominent notices\
+ stating that you changed the files and the date of any change.\
+\
+ b) You must cause any work that you distribute or publish, that in\
+ whole or in part contains or is derived from the Program or any\
+ part thereof, to be licensed as a whole at no charge to all third\
+ parties under the terms of this License.\
+\
+ c) If the modified program normally reads commands interactively\
+ when run, you must cause it, when started running for such\
+ interactive use in the most ordinary way, to print or display an\
+ announcement including an appropriate copyright notice and a\
+ notice that there is no warranty (or else, saying that you provide\
+ a warranty) and that users may redistribute the program under\
+ these conditions, and telling the user how to view a copy of this\
+ License. (Exception: if the Program itself is interactive but\
+ does not normally print such an announcement, your work based on\
+ the Program is not required to print an announcement.)\
+\page \
+These requirements apply to the modified work as a whole. If\
+identifiable sections of that work are not derived from the Program,\
+and can be reasonably considered independent and separate works in\
+themselves, then this License, and its terms, do not apply to those\
+sections when you distribute them as separate works. But when you\
+distribute the same sections as part of a whole which is a work based\
+on the Program, the distribution of the whole must be on the terms of\
+this License, whose permissions for other licensees extend to the\
+entire whole, and thus to each and every part regardless of who wrote it.\
+\
+Thus, it is not the intent of this section to claim rights or contest\
+your rights to work written entirely by you; rather, the intent is to\
+exercise the right to control the distribution of derivative or\
+collective works based on the Program.\
+\
+In addition, mere aggregation of another work not based on the Program\
+with the Program (or with a work based on the Program) on a volume of\
+a storage or distribution medium does not bring the other work under\
+the scope of this License.\
+\
+ 3. You may copy and distribute the Program (or a work based on it,\
+under Section 2) in object code or executable form under the terms of\
+Sections 1 and 2 above provided that you also do one of the following:\
+\
+ a) Accompany it with the complete corresponding machine-readable\
+ source code, which must be distributed under the terms of Sections\
+ 1 and 2 above on a medium customarily used for software interchange; or,\
+\
+ b) Accompany it with a written offer, valid for at least three\
+ years, to give any third party, for a charge no more than your\
+ cost of physically performing source distribution, a complete\
+ machine-readable copy of the corresponding source code, to be\
+ distributed under the terms of Sections 1 and 2 above on a medium\
+ customarily used for software interchange; or,\
+\
+ c) Accompany it with the information you received as to the offer\
+ to distribute corresponding source code. (This alternative is\
+ allowed only for noncommercial distribution and only if you\
+ received the program in object code or executable form with such\
+ an offer, in accord with Subsection b above.)\
+\
+The source code for a work means the preferred form of the work for\
+making modifications to it. For an executable work, complete source\
+code means all the source code for all modules it contains, plus any\
+associated interface definition files, plus the scripts used to\
+control compilation and installation of the executable. However, as a\
+special exception, the source code distributed need not include\
+anything that is normally distributed (in either source or binary\
+form) with the major components (compiler, kernel, and so on) of the\
+operating system on which the executable runs, unless that component\
+itself accompanies the executable.\
+\
+If distribution of executable or object code is made by offering\
+access to copy from a designated place, then offering equivalent\
+access to copy the source code from the same place counts as\
+distribution of the source code, even though third parties are not\
+compelled to copy the source along with the object code.\
+\page \
+ 4. You may not copy, modify, sublicense, or distribute the Program\
+except as expressly provided under this License. Any attempt\
+otherwise to copy, modify, sublicense or distribute the Program is\
+void, and will automatically terminate your rights under this License.\
+However, parties who have received copies, or rights, from you under\
+this License will not have their licenses terminated so long as such\
+parties remain in full compliance.\
+\
+ 5. You are not required to accept this License, since you have not\
+signed it. However, nothing else grants you permission to modify or\
+distribute the Program or its derivative works. These actions are\
+prohibited by law if you do not accept this License. Therefore, by\
+modifying or distributing the Program (or any work based on the\
+Program), you indicate your acceptance of this License to do so, and\
+all its terms and conditions for copying, distributing or modifying\
+the Program or works based on it.\
+\
+ 6. Each time you redistribute the Program (or any work based on the\
+Program), the recipient automatically receives a license from the\
+original licensor to copy, distribute or modify the Program subject to\
+these terms and conditions. You may not impose any further\
+restrictions on the recipients' exercise of the rights granted herein.\
+You are not responsible for enforcing compliance by third parties to\
+this License.\
+\
+ 7. If, as a consequence of a court judgment or allegation of patent\
+infringement or for any other reason (not limited to patent issues),\
+conditions are imposed on you (whether by court order, agreement or\
+otherwise) that contradict the conditions of this License, they do not\
+excuse you from the conditions of this License. If you cannot\
+distribute so as to satisfy simultaneously your obligations under this\
+License and any other pertinent obligations, then as a consequence you\
+may not distribute the Program at all. For example, if a patent\
+license would not permit royalty-free redistribution of the Program by\
+all those who receive copies directly or indirectly through you, then\
+the only way you could satisfy both it and this License would be to\
+refrain entirely from distribution of the Program.\
+\
+If any portion of this section is held invalid or unenforceable under\
+any particular circumstance, the balance of the section is intended to\
+apply and the section as a whole is intended to apply in other\
+circumstances.\
+\
+It is not the purpose of this section to induce you to infringe any\
+patents or other property right claims or to contest validity of any\
+such claims; this section has the sole purpose of protecting the\
+integrity of the free software distribution system, which is\
+implemented by public license practices. Many people have made\
+generous contributions to the wide range of software distributed\
+through that system in reliance on consistent application of that\
+system; it is up to the author/donor to decide if he or she is willing\
+to distribute software through any other system and a licensee cannot\
+impose that choice.\
+\
+This section is intended to make thoroughly clear what is believed to\
+be a consequence of the rest of this License.\
+\page \
+ 8. If the distribution and/or use of the Program is restricted in\
+certain countries either by patents or by copyrighted interfaces, the\
+original copyright holder who places the Program under this License\
+may add an explicit geographical distribution limitation excluding\
+those countries, so that distribution is permitted only in or among\
+countries not thus excluded. In such case, this License incorporates\
+the limitation as if written in the body of this License.\
+\
+ 9. The Free Software Foundation may publish revised and/or new versions\
+of the General Public License from time to time. Such new versions will\
+be similar in spirit to the present version, but may differ in detail to\
+address new problems or concerns.\
+\
+Each version is given a distinguishing version number. If the Program\
+specifies a version number of this License which applies to it and "any\
+later version", you have the option of following the terms and conditions\
+either of that version or of any later version published by the Free\
+Software Foundation. If the Program does not specify a version number of\
+this License, you may choose any version ever published by the Free Software\
+Foundation.\
+\
+ 10. If you wish to incorporate parts of the Program into other free\
+programs whose distribution conditions are different, write to the author\
+to ask for permission. For software which is copyrighted by the Free\
+Software Foundation, write to the Free Software Foundation; we sometimes\
+make exceptions for this. Our decision will be guided by the two goals\
+of preserving the free status of all derivatives of our free software and\
+of promoting the sharing and reuse of software generally.\
+\
+ NO WARRANTY\
+\
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\
+REPAIR OR CORRECTION.\
+\
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\
+POSSIBILITY OF SUCH DAMAGES.\
+\
+ END OF TERMS AND CONDITIONS\
+\page \
+ How to Apply These Terms to Your New Programs\
+\
+ If you develop a new program, and you want it to be of the greatest\
+possible use to the public, the best way to achieve this is to make it\
+free software which everyone can redistribute and change under these terms.\
+\
+ To do so, attach the following notices to the program. It is safest\
+to attach them to the start of each source file to most effectively\
+convey the exclusion of warranty; and each file should have at least\
+the "copyright" line and a pointer to where the full notice is found.\
+\
+ <one line to give the program's name and a brief idea of what it does.>\
+ Copyright (C) <year> <name of author>\
+\
+ This program is free software; you can redistribute it and/or modify\
+ it under the terms of the GNU General Public License as published by\
+ the Free Software Foundation; either version 2 of the License, or\
+ (at your option) any later version.\
+\
+ This program is distributed in the hope that it will be useful,\
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\
+ GNU General Public License for more details.\
+\
+ You should have received a copy of the GNU General Public License\
+ along with this program; if not, write to the Free Software\
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\
+\
+\
+Also add information on how to contact you by electronic and paper mail.\
+\
+If the program is interactive, make it output a short notice like this\
+when it starts in an interactive mode:\
+\
+ Gnomovision version 69, Copyright (C) year name of author\
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\
+ This is free software, and you are welcome to redistribute it\
+ under certain conditions; type `show c' for details.\
+\
+The hypothetical commands `show w' and `show c' should show the appropriate\
+parts of the General Public License. Of course, the commands you use may\
+be called something other than `show w' and `show c'; they could even be\
+mouse-clicks or menu items--whatever suits your program.\
+\
+You should also get your employer (if you work as a programmer) or your\
+school, if any, to sign a "copyright disclaimer" for the program, if\
+necessary. Here is a sample; alter the names:\
+\
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program\
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.\
+\
+ <signature of Ty Coon>, 1 April 1989\
+ Ty Coon, President of Vice\
+\
+This General Public License does not permit incorporating your program into\
+proprietary programs. If your program is a subroutine library, you may\
+consider it more useful to permit linking proprietary applications with the\
+library. If this is what you want to do, use the GNU Library General\
+Public License instead of this License.\
+}
--- /dev/null
+@echo off\r
+"%~dp0\mono.exe" %MONO_OPTIONS% "%~dp0\..\lib\mono\@@RUNTIME@@\@@COMMAND@@" %*\r
if [ "$$ok" = "false" ]; then echo "<?xml version='1.0' encoding='utf-8'?><test-results failures='1' total='1' not-run='0' name='verify' date='$$(date +%F)' time='$$(date +%T)'><test-suite name='mcs-compileall' success='False' time='0'><results><test-case name='fail' executed='True' success='False' time='0'><failure><message>Verifying framework assemblies failed. Check the log for more details.</message><stack-trace></stack-trace></failure></test-case></results></test-suite></test-results>" > TestResult-verify.xml; fi; \
$$ok
-if NACL_CODEGEN
-check-local:
-else
check-local: mcs-compileall mcs-do-test-profiles
$(MAKE) mcs-do-run-test-profiles
-endif
# Compile all mcs tests
test: mcs-do-test-profiles
PATH="$r/runtime/_tmpinst/bin:$PATH"
MONO_EXECUTABLE=${MONO_EXECUTABLE:-"$r/@mono_runtime@"}
export MONO_CFG_DIR PATH
-if [ -n "@nacl_self_host@" ]; then
- case "$@" in
- # gacutil.exe and mdoc.exe require filesystem functionality not
- # exposed in NaCl.
- # mcs.exe was added to the list recently because mcs under NaCl
- # no longer produces equivalent output. TODO: investigate
- */mcs.exe* | */gacutil.exe* | */mdoc.exe* ) exec /usr/local/bin/mono "$@";;
- esac
-fi
exec "$r/libtool" --mode=execute "${MONO_EXECUTABLE}" --config "@mono_cfg_dir@/mono/config" "$@"
${TESTCMD} --label=Microsoft.Build.Tasks --timeout=5m make -w -C mcs/class/Microsoft.Build.Tasks run-test
${TESTCMD} --label=Microsoft.Build.Utilities --timeout=5m make -w -C mcs/class/Microsoft.Build.Utilities run-test
${TESTCMD} --label=Mono.C5 --timeout=5m make -w -C mcs/class/Mono.C5 run-test
+${TESTCMD} --label=Mono.Options --timeout=5m make -w -C mcs/class/Mono.Options run-test
${TESTCMD} --label=Mono.Tasklets --timeout=5m make -w -C mcs/class/Mono.Tasklets run-test
${TESTCMD} --label=System.Configuration --timeout=5m make -w -C mcs/class/System.Configuration run-test
${TESTCMD} --label=System.Transactions --timeout=5m make -w -C mcs/class/System.Transactions run-test
${TESTCMD} --label=Mono.CSharp --timeout=5m make -w -C mcs/class/Mono.CSharp run-test
${TESTCMD} --label=WindowsBase --timeout=5m make -w -C mcs/class/WindowsBase run-test
${TESTCMD} --label=System.Numerics --timeout=5m make -w -C mcs/class/System.Numerics run-test
+if [[ ${label} == w* ]]; then ${TESTCMD} --label=System.Numerics-xunit --skip; else ${TESTCMD} --label=System.Numerics-xunit --timeout=5m make -w -C mcs/class/System.Numerics run-xunit-test; fi
${TESTCMD} --label=System.Runtime.DurableInstancing --timeout=5m make -w -C mcs/class/System.Runtime.DurableInstancing run-test
${TESTCMD} --label=System.ServiceModel.Discovery --timeout=5m make -w -C mcs/class/System.ServiceModel.Discovery run-test
${TESTCMD} --label=System.Xaml --timeout=5m make -w -C mcs/class/System.Xaml run-test
"SeqPointInfo",
"DynCallArgs",
"MonoLMFTramp",
+ "InterpMethodArguments",
};
DumpClasses(writer, ctx, optionalTypes, optional: true);
/* Using the simple generational GC. */
/* #undef HAVE_SGEN_GC */
+/* Some VES is available at runtime */
+#define HAVE_ONLINE_VES 1
+
/* Have signal */
#define HAVE_SIGNAL 1