From 3cc9601fd97a6234728bcbecbda3754df0d927e7 Mon Sep 17 00:00:00 2001 From: "Xamarin Public Jenkins (auto-signing)" Date: Fri, 9 Sep 2016 07:19:48 +0000 Subject: [PATCH] Imported Upstream version 4.6.0.243 Former-commit-id: ff34202749e8df2aa83f2578b16260b444f50987 --- libgc/include/gc.h | 1 + man/mprof-report.1 | 99 +- .../Mono.Data.Sqlite_2.0/SQLite3.cs | 4 +- .../Mono.Data.Sqlite_2.0/SQLiteBase.cs | 4 +- .../UnsafeNativeMethods.cs | 28 + .../common_System.Core.dll.sources | 5 + .../net_4_x_System.Core.dll.sources | 5 - mcs/class/System/System.Net/HttpWebRequest.cs | 2 +- .../System.Security/SafeAccessTokenHandle.cs | 25 - .../corlib/System.Text/Latin1Encoding.cs | 6 +- mcs/class/corlib/System/Environment.cs | 24 + .../Test/System.Text/ASCIIEncodingTest.cs | 43 + .../Test/System.Text/Latin1EncodingTest.cs | 350 ++ mcs/class/corlib/corlib.dll.sources | 2 +- mcs/class/corlib/corlib_test.dll.sources | 1 + .../Actions/DynamicObject.cs | 39 + .../monolite/System.Core.dll.REMOVED.git-id | 2 +- .../lib/monolite/System.dll.REMOVED.git-id | 2 +- .../lib/monolite/basic.exe.REMOVED.git-id | 2 +- .../lib/monolite/mscorlib.dll.REMOVED.git-id | 2 +- .../system/security/safesecurityhandles.cs | 4 + mcs/mcs/cs-tokenizer.cs | 6 +- mcs/tests/dtest-065.cs | 28 + mcs/tests/test-debug-30-ref.xml | 11 +- mcs/tests/test-debug-30.cs | 8 + mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id | 2 +- mono/metadata/appdomain.c | 95 +- mono/metadata/assembly.c | 3653 ----------------- mono/metadata/assembly.c.REMOVED.git-id | 1 + mono/metadata/boehm-gc.c | 18 +- mono/metadata/class.c.REMOVED.git-id | 2 +- mono/metadata/domain-internals.h | 4 + mono/metadata/domain.c | 10 + mono/metadata/gc-internals.h | 4 - mono/metadata/gc.c | 8 + mono/metadata/jit-info.c | 8 +- mono/metadata/mono-config.c | 33 + mono/metadata/mono-config.h | 4 + mono/metadata/mono-gc.h | 2 + mono/metadata/profiler-private.h | 5 + mono/metadata/profiler.c | 49 + mono/metadata/profiler.h | 26 +- mono/metadata/sgen-mono.c | 2 +- mono/metadata/sgen-stw.c | 4 + mono/mini/Makefile.am | 2 +- mono/mini/Makefile.am.in | 2 +- mono/mini/Makefile.in.REMOVED.git-id | 2 +- mono/mini/jit-icalls.c | 5 + mono/mini/jit-icalls.h | 2 + mono/mini/method-to-ir.c.REMOVED.git-id | 2 +- mono/mini/mini-amd64.c.REMOVED.git-id | 2 +- mono/mini/mini-arm.c.REMOVED.git-id | 2 +- mono/mini/mini-ia64.c.REMOVED.git-id | 2 +- mono/mini/mini-llvm.c.REMOVED.git-id | 2 +- mono/mini/mini-mips.c.REMOVED.git-id | 2 +- mono/mini/mini-ppc.c.REMOVED.git-id | 2 +- mono/mini/mini-runtime.c.REMOVED.git-id | 2 +- mono/mini/mini-s390x.c.REMOVED.git-id | 2 +- mono/mini/mini-sparc.c.REMOVED.git-id | 2 +- mono/mini/mini-x86.c.REMOVED.git-id | 2 +- mono/mini/version.h | 2 +- mono/profiler/decode.c.REMOVED.git-id | 2 +- mono/profiler/proflog.c.REMOVED.git-id | 2 +- mono/profiler/proflog.h | 72 +- mono/profiler/utils.c | 2 +- mono/sgen/sgen-marksweep.c | 5 +- mono/tests/Makefile.am | 20 +- mono/tests/Makefile.in | 21 +- mono/tests/reference-loader.cs | 111 + mono/unit-tests/test-mono-linked-list-set.c | 10 +- mono/utils/Makefile.am | 31 +- mono/utils/Makefile.in | 71 +- mono/utils/atomic.h | 191 +- mono/utils/hazard-pointer.c | 64 +- mono/utils/hazard-pointer.h | 18 +- mono/utils/lock-free-alloc.c | 2 +- mono/utils/lock-free-queue.c | 4 +- mono/utils/mono-compiler.h | 4 + mono/utils/mono-conc-hashtable.c | 2 +- mono/utils/mono-hwcap-arm.c | 24 +- mono/utils/mono-hwcap-arm.h | 15 - mono/utils/mono-hwcap-arm64.c | 16 +- mono/utils/mono-hwcap-arm64.h | 6 - mono/utils/mono-hwcap-cross.c | 16 + mono/utils/mono-hwcap-ia64.c | 8 +- mono/utils/mono-hwcap-ia64.h | 8 - mono/utils/mono-hwcap-mips.c | 8 +- mono/utils/mono-hwcap-mips.h | 8 - mono/utils/mono-hwcap-ppc.c | 18 +- mono/utils/mono-hwcap-ppc.h | 12 - mono/utils/mono-hwcap-s390x.c | 115 +- mono/utils/mono-hwcap-s390x.h | 101 - mono/utils/mono-hwcap-sparc.c | 14 +- mono/utils/mono-hwcap-sparc.h | 8 - mono/utils/mono-hwcap-vars.h | 56 + mono/utils/mono-hwcap-x86.c | 29 +- mono/utils/mono-hwcap-x86.h | 17 - mono/utils/mono-hwcap.c | 28 +- mono/utils/mono-hwcap.h | 11 +- mono/utils/mono-linked-list-set.c | 35 +- mono/utils/mono-linked-list-set.h | 25 +- mono/utils/mono-membar.h | 15 - mono/utils/mono-threads.c | 8 +- mono/utils/mono-threads.h | 2 +- po/mcs/de.gmo | Bin 5406 -> 5406 bytes po/mcs/de.po.REMOVED.git-id | 2 +- po/mcs/es.gmo | Bin 16329 -> 16329 bytes po/mcs/es.po.REMOVED.git-id | 2 +- po/mcs/ja.gmo | Bin 20863 -> 20863 bytes po/mcs/ja.po.REMOVED.git-id | 2 +- po/mcs/mcs.pot | 2 +- po/mcs/pt_BR.gmo | Bin 73161 -> 73161 bytes po/mcs/pt_BR.po.REMOVED.git-id | 2 +- 113 files changed, 1476 insertions(+), 4439 deletions(-) delete mode 100644 mcs/class/corlib/System.Security/SafeAccessTokenHandle.cs create mode 100644 mcs/class/corlib/Test/System.Text/Latin1EncodingTest.cs create mode 100644 mcs/tests/dtest-065.cs delete mode 100644 mono/metadata/assembly.c create mode 100644 mono/metadata/assembly.c.REMOVED.git-id create mode 100644 mono/tests/reference-loader.cs delete mode 100644 mono/utils/mono-hwcap-arm.h delete mode 100644 mono/utils/mono-hwcap-arm64.h create mode 100644 mono/utils/mono-hwcap-cross.c delete mode 100644 mono/utils/mono-hwcap-ia64.h delete mode 100644 mono/utils/mono-hwcap-mips.h delete mode 100644 mono/utils/mono-hwcap-ppc.h delete mode 100644 mono/utils/mono-hwcap-s390x.h delete mode 100644 mono/utils/mono-hwcap-sparc.h create mode 100644 mono/utils/mono-hwcap-vars.h delete mode 100644 mono/utils/mono-hwcap-x86.h diff --git a/libgc/include/gc.h b/libgc/include/gc.h index e7929918ad..7b1460a888 100644 --- a/libgc/include/gc.h +++ b/libgc/include/gc.h @@ -93,6 +93,7 @@ GC_API GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)); /* pointer to a previously allocated heap */ /* object. */ +// Keep somewhat in sync with mono/metadata/profiler.h:enum MonoGCEvent typedef enum { GC_EVENT_START, GC_EVENT_MARK_START, diff --git a/man/mprof-report.1 b/man/mprof-report.1 index af61efa37c..c2020a7445 100644 --- a/man/mprof-report.1 +++ b/man/mprof-report.1 @@ -1,4 +1,8 @@ -.TH mprof-report 1 "" +.de Sp +.if t .sp .5v +.if n .sp +.. +.TH mprof-report 1 "" .SH The Mono log profiler .PP The Mono \f[I]log\f[] profiler can be used to collect a lot of @@ -237,6 +241,9 @@ Methods JITted using mono JIT, Methods JITted using LLVM, Total time spent JITting (sec), User Time, System Time, Total Time, Working Set, Private Bytes, Virtual Bytes, Page Faults and CPU Load Average (1min, 5min and 15min). +.IP \[bu] 2 +\f[I]coverage\f[]: collect code coverage data. This implies enabling +the \f[I]calls\f[] option. .RE .SS Analyzing the profile data .PP @@ -260,7 +267,7 @@ To see this info invoke mprof-report as follows: \f[B]mprof-report\ --traces\ output.mlpd\f[] .PP The maximum number of methods in each stack trace can be specified -with the \f[I]\[em]maxframes=NUM\f[] option: +with the \f[I]--maxframes=NUM\f[] option: .PP \f[B]mprof-report\ --traces\ --maxframes=4\ output.mlpd\f[] .PP @@ -272,7 +279,7 @@ specific events when the \f[I]nocalls\f[] option is used, so in that case, if more stack frames are required in mprof-report, a bigger value for maxframes when profiling must be used, too. .PP -The \f[I]\[em]traces\f[] option also controls the reverse reference +The \f[I]--traces\f[] option also controls the reverse reference feature in the heapshot report: for each class it reports how many references to objects of that class come from other classes. .SS Sort order for methods and allocations @@ -362,6 +369,10 @@ version \f[I]heapshot\f[]: live heap usage at heap shots .IP \[bu] 2 \f[I]counters\f[]: counters samples +.IP \[bu] 2 +\f[I]coverage\f[]: code coverage data +.IP \[bu] 2 +\f[I]stats\f[]: event statistics .PP It is possible to limit some of the data displayed to a timeframe of the program execution with the option: @@ -391,23 +402,23 @@ Instead of printing the usual reports from the profiler data, it is possible to track some interesting information about some specific object addresses. The objects are selected based on their address with the -\f[I]\[em]track\f[] option as follows: +\f[I]--track\f[] option as follows: .PP \f[B]--track=0xaddr1[,0xaddr2,...]\f[] .PP The reported info (if available in the data file), will be class name, size, creation time, stack trace of creation (with the -\f[I]\[em]traces\f[] option), etc. +\f[I]--traces\f[] option), etc. If heapshot data is available it will be possible to also track what other objects reference one of the listed addresses. .PP The object addresses can be gathered either from the profiler report in some cases (like in the monitor lock report), from the live application or they can be selected with the -\f[I]\[em]find=FINDSPEC\f[] option. +\f[I]--find=FINDSPEC\f[] option. FINDSPEC can be one of the following: .IP \[bu] 2 -\f[I]S:SIZE\f[]: where the object is selected if it's size is at +\f[I]S:SIZE\f[]: where the object is selected if its size is at least \f[I]SIZE\f[] .IP \[bu] 2 \f[I]T:NAME\f[]: where the object is selected if \f[I]NAME\f[] @@ -432,6 +443,13 @@ By default mprof-report will print the summary data to the console. To print it to a file, instead, use the option: .PP \f[B]--out=FILENAME\f[] +.SS Processing code coverage data +.PP +If you ran the profiler with the \f[I]coverage\f[] option, you can +process the collected coverage data into an XML file by running +mprof-report like this: +.PP +\f[B]mprof-report --coverage-out=coverage.xml output.mlpd\f[] .SS Dealing with profiler slowness .PP If the profiler needs to collect lots of data, the execution of the @@ -439,20 +457,20 @@ program will slow down significantly, usually 10 to 20 times slower. There are several ways to reduce the impact of the profiler on the program execution. -.SS Use the statistical sampling mode -.PP +.IP "\f[I]Use the statistical sampling mode\f[]" 4 +.Sp Statistical sampling allows executing a program under the profiler with minimal performance overhead (usually less than 10%). This mode allows checking where the program is spending most of -it's execution time without significantly perturbing its behaviour. -.SS Collect less data -.PP +its execution time without significantly perturbing its behaviour. +.IP "\f[I]Collect less data\f[]" 4 +.Sp Collecting method enter/leave events can be very expensive, especially in programs that perform many millions of tiny calls. The profiler option \f[I]nocalls\f[] can be used to avoid collecting this data or it can be limited to only a few call levels with the \f[I]calldepth\f[] option. -.PP +.Sp Object allocation information is expensive as well, though much less than method enter/leave events. If it's not needed, it can be skipped with the \f[I]noalloc\f[] @@ -463,14 +481,14 @@ expensive as well. The impact of stack trace information can be reduced by setting a low value with the \f[I]maxframes\f[] option or by eliminating them completely, by setting it to 0. -.PP -The other major source of data is the heapshot profiler option: -especially if the managed heap is big, since every object needs to -be inspected. +.Sp +The other major source of data is the \f[I]heapshot\f[] profiler +option: especially if the managed heap is big, since every object +needs to be inspected. The \f[I]MODE\f[] parameter of the \f[I]heapshot\f[] option can be used to reduce the frequency of the heap shots. -.SS Reduce the timestamp overhead -.PP +.IP "\f[I]Reduce the timestamp overhead\f[]" 4 +.Sp On many operating systems or architectures what actually slows down profiling is the function provided by the system to get timestamp information. @@ -486,15 +504,15 @@ There are a few ways to minimize the amount of data, for example by not collecting some of the more space-consuming information or by compressing the information on the fly or by just generating a summary report. -.SS Reducing the amount of data -.PP +.IP "\f[I]Reducing the amount of data\f[]" 4 +.Sp Method enter/leave events can be excluded completely with the \f[I]nocalls\f[] option or they can be limited to just a few levels of calls with the \f[I]calldepth\f[] option. For example, the option: -.PP +.Sp \f[B]calldepth=10\f[] -.PP +.Sp will ignore the method events when there are more than 10 managed stack frames. This is very useful for programs that have deep recursion or for @@ -503,59 +521,59 @@ the call stack. The optimal number for the calldepth option depends on the program and it needs to be balanced between providing enough profiling information and allowing fast execution speed. -.PP +.Sp Note that by default, if method events are not recorded at all, the profiler will collect stack trace information at events like allocations. To avoid gathering this data, use the \f[I]maxframes=0\f[] profiler option. -.PP +.Sp Allocation events can be eliminated with the \f[I]noalloc\f[] option. -.PP +.Sp Heap shot data can also be huge: by default it is collected at each major collection. To reduce the frequency, you can specify a heapshot mode: for example to collect every 5 collections (including major and minor): -.PP +.Sp \f[B]heapshot=5gc\f[] -.PP +.Sp or when at least 5 seconds passed since the last heap shot: -.PP +.Sp \f[B]heapshot=5000ms\f[] -.SS Compressing the data -.PP +.IP "\f[I]Compressing the data\f[]" 4 +.Sp To reduce the amout of disk space used by the data, the data can be compressed either after it has been generated with the gzip command: -.PP +.Sp \f[B]gzip\ -9\ output.mlpd\f[] -.PP +.Sp or it can be compressed automatically by using the \f[I]zip\f[] profiler option. Note that in this case there could be a significant slowdown of the profiled program. -.PP +.Sp The mprof-report program will tranparently deal with either compressed or uncompressed data files. -.SS Generating only a summary report -.PP +.IP "\f[I]Generating only a summary report\f[]" 4 +.Sp Often it's enough to look at the profiler summary report to diagnose an issue and in this case it's possible to avoid saving the profiler data file to disk. This can be accomplished with the \f[I]report\f[] profiler option, which will basically send the data to the mprof-report program for display. -.PP +.Sp To have more control of what summary information is reported (or to use a completely different program to decode the profiler data), the \f[I]output\f[] profiler option can be used, with \f[B]|\f[] as the first character: the rest of the output name will be executed as a program with the data fed in on the standard input. -.PP +.Sp For example, to print only the Monitor summary with stack trace information, you could use it like this: -.PP +.Sp \f[B]output=|mprof-report\ --reports=monitor\ --traces\ -\f[] .SH WEB SITE http://www.mono-project.com/docs/debug+profile/profile/profiler/ @@ -563,5 +581,4 @@ http://www.mono-project.com/docs/debug+profile/profile/profiler/ .PP mono(1) .SH AUTHORS -Paolo Molaro. - +Paolo Molaro, Alex Rønne Petersen diff --git a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs index 6f757238cd..34556edb93 100644 --- a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs +++ b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs @@ -125,9 +125,9 @@ namespace Mono.Data.Sqlite // Compatibility with versions < 3.5.0 int n; - try { + if (UnsafeNativeMethods.use_sqlite3_open_v2) { n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero); - } catch (EntryPointNotFoundException) { + } else { Console.WriteLine ("Your sqlite3 version is old - please upgrade to at least v3.5.0!"); n = UnsafeNativeMethods.sqlite3_open (ToUTF8 (strFilename), out db); } diff --git a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteBase.cs b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteBase.cs index df8a5d787a..eca1bddfc6 100644 --- a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteBase.cs +++ b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteBase.cs @@ -208,9 +208,9 @@ namespace Mono.Data.Sqlite #else ResetConnection(db); int n; - try { + if (UnsafeNativeMethods.use_sqlite3_close_v2) { n = UnsafeNativeMethods.sqlite3_close_v2(db); - } catch (EntryPointNotFoundException) { + } else { n = UnsafeNativeMethods.sqlite3_close(db); } #endif diff --git a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs index ba16a1763f..bc9826d29f 100644 --- a/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs +++ b/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs @@ -16,6 +16,27 @@ namespace Mono.Data.Sqlite #endif internal static class UnsafeNativeMethods { + internal static readonly bool use_sqlite3_close_v2 = false; + internal static readonly bool use_sqlite3_open_v2 = false; + internal static readonly bool use_sqlite3_create_function_v2 = false; + static UnsafeNativeMethods() + { + // calculate the version number parts + // https://www.sqlite.org/c3ref/c_source_id.html + // ( * 1000000) + ( * 1000) + () + int versionNumber = sqlite3_libversion_number(); + int release = versionNumber % 1000; + int minor = (versionNumber / 1000) % 1000; + int major = versionNumber / 1000000; + Version version = new Version(major, minor, release); + + // set the various versions + // https://sqlite.org/changes.html + use_sqlite3_open_v2 = version >= new Version(3, 5, 0); + use_sqlite3_close_v2 = version >= new Version(3, 7, 14); + use_sqlite3_create_function_v2 = version >= new Version(3, 7, 3); + } + #if !SQLITE_STANDARD #if !USE_INTEROP_DLL @@ -730,6 +751,13 @@ namespace Mono.Data.Sqlite #endif internal static extern int sqlite3_free (IntPtr ptr); +#if !PLATFORM_COMPACTFRAMEWORK + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] +#else + [DllImport(SQLITE_DLL)] +#endif + internal static extern int sqlite3_libversion_number(); + #endregion } diff --git a/mcs/class/System.Core/common_System.Core.dll.sources b/mcs/class/System.Core/common_System.Core.dll.sources index f6a3f9b546..6e36c961e3 100644 --- a/mcs/class/System.Core/common_System.Core.dll.sources +++ b/mcs/class/System.Core/common_System.Core.dll.sources @@ -21,10 +21,15 @@ System.IO.Pipes/AnonymousPipeClientStream.cs System.IO.Pipes/AnonymousPipeServerStream.cs System.IO.Pipes/NamedPipeClientStream.cs System.IO.Pipes/NamedPipeServerStream.cs +System.IO.Pipes/PipeAccessRights.cs +System.IO.Pipes/PipeAccessRule.cs +System.IO.Pipes/PipeAuditRule.cs System.IO.Pipes/PipeDirection.cs System.IO.Pipes/PipeInterfaces.cs System.IO.Pipes/PipeOptions.cs +System.IO.Pipes/PipeSecurity.cs System.IO.Pipes/PipeStream.cs +System.IO.Pipes/PipeStreamImpersonationWorker.cs System.IO.Pipes/PipeTransmissionMode.cs ReferenceSources/SR.cs diff --git a/mcs/class/System.Core/net_4_x_System.Core.dll.sources b/mcs/class/System.Core/net_4_x_System.Core.dll.sources index f367efd60c..72d7865921 100644 --- a/mcs/class/System.Core/net_4_x_System.Core.dll.sources +++ b/mcs/class/System.Core/net_4_x_System.Core.dll.sources @@ -1,11 +1,6 @@ #include common_System.Core.dll.sources #include dynamic_System.Core.dll.sources -System.IO.Pipes/PipeAccessRights.cs -System.IO.Pipes/PipeAccessRule.cs -System.IO.Pipes/PipeAuditRule.cs -System.IO.Pipes/PipeSecurity.cs -System.IO.Pipes/PipeStreamImpersonationWorker.cs System.IO.Pipes/PipeUnix.cs System.IO.Pipes/PipeWin32.cs diff --git a/mcs/class/System/System.Net/HttpWebRequest.cs b/mcs/class/System/System.Net/HttpWebRequest.cs index 828765d9db..676448649b 100644 --- a/mcs/class/System/System.Net/HttpWebRequest.cs +++ b/mcs/class/System/System.Net/HttpWebRequest.cs @@ -450,7 +450,7 @@ namespace System.Net newWebHeaders.Add(headerName,webHeaders[headerName]); } - webHeaders = newWebHeaders; + this.webHeaders = newWebHeaders; } } diff --git a/mcs/class/corlib/System.Security/SafeAccessTokenHandle.cs b/mcs/class/corlib/System.Security/SafeAccessTokenHandle.cs deleted file mode 100644 index d7682bfd2f..0000000000 --- a/mcs/class/corlib/System.Security/SafeAccessTokenHandle.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Microsoft.Win32.SafeHandles -{ - public sealed class SafeAccessTokenHandle : SafeHandle - { - public override bool IsInvalid { - get { - return handle == IntPtr.Zero; - } - } - - public SafeAccessTokenHandle () - : base (IntPtr.Zero, true) - { - - } - - protected override bool ReleaseHandle() - { - return true; - } - } -} diff --git a/mcs/class/corlib/System.Text/Latin1Encoding.cs b/mcs/class/corlib/System.Text/Latin1Encoding.cs index f64237aaf6..0d87d5624e 100644 --- a/mcs/class/corlib/System.Text/Latin1Encoding.cs +++ b/mcs/class/corlib/System.Text/Latin1Encoding.cs @@ -157,7 +157,11 @@ internal class Latin1Encoding : Encoding buffer = EncoderFallback.CreateFallbackBuffer (); if (Char.IsSurrogate (ch) && count > 1 && Char.IsSurrogate (chars [charIndex])) - buffer.Fallback (ch, chars [charIndex], charIndex++ - 1); + { + buffer.Fallback (ch, chars [charIndex], charIndex - 1); + charIndex++; + count--; + } else buffer.Fallback (ch, charIndex - 1); if (fallback_chars == null || fallback_chars.Length < buffer.Remaining) diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index fd5e734534..ebef8e6ca4 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -862,6 +862,22 @@ namespace System { } } #else + public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + return GetEnvironmentVariable (variable); + + return null; + } + + public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + return GetEnvironmentVariables (); + + return (IDictionary)new Hashtable (); + } + public static void SetEnvironmentVariable (string variable, string value) { if (variable == null) @@ -875,6 +891,14 @@ namespace System { InternalSetEnvironmentVariable (variable, value); } + + public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + SetEnvironmentVariable (variable, value); + + // other targets ignored + } #endif [MethodImplAttribute (MethodImplOptions.InternalCall)] internal static extern void InternalSetEnvironmentVariable (string variable, string value); diff --git a/mcs/class/corlib/Test/System.Text/ASCIIEncodingTest.cs b/mcs/class/corlib/Test/System.Text/ASCIIEncodingTest.cs index 16fca588d1..f35a9d3883 100644 --- a/mcs/class/corlib/Test/System.Text/ASCIIEncodingTest.cs +++ b/mcs/class/corlib/Test/System.Text/ASCIIEncodingTest.cs @@ -119,6 +119,40 @@ namespace MonoTests.System.Text Assert.AreEqual (testchars [i], (char) bytes [i]); } + [Test] // Test GetBytes(string) + public void TestGetBytes7 () + { + var latin1_encoding = Encoding.GetEncoding ("latin1"); + + var expected = new byte [] { 0x3F, 0x20, 0x3F, 0x20, 0x3F }; + var actual = latin1_encoding.GetBytes("\u24c8 \u2075 \u221e"); // normal replacement + Assert.AreEqual (expected, actual, "#1"); + + expected = new byte [] { 0x3F, 0x3F }; + actual = latin1_encoding.GetBytes("\ud83d\ude0a"); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#2"); + + expected = new byte [] { 0x3F, 0x3F, 0x20 }; + actual = latin1_encoding.GetBytes("\ud83d\ude0a "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#3"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud83d\ude0a "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#4"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud834\udd1e "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#5"); + + expected = new byte [] { 0x41, 0x42, 0x43, 0x00, 0x41, 0x42, 0x43 }; + actual = latin1_encoding.GetBytes("ABC\0ABC"); // embedded zero byte not replaced + Assert.AreEqual (expected, actual, "#6"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud834 "); // invalid surrogate pair replacement + Assert.AreEqual (expected, actual, "#7"); + } + [Test] // Test GetChars(byte[]) public void TestGetChars1 () { @@ -212,6 +246,15 @@ namespace MonoTests.System.Text Assert.AreEqual (string.Empty, encoding.GetString (new byte [0], 0, 0), "#2"); } + [Test] + [ExpectedException (typeof (EncoderFallbackException))] + public void EncoderFallback () + { + Encoding e = Encoding.ASCII.Clone () as Encoding; + e.EncoderFallback = new EncoderExceptionFallback (); + e.GetBytes ("\u24c8"); + } + [Test] [ExpectedException (typeof (DecoderFallbackException))] public void DecoderFallback () diff --git a/mcs/class/corlib/Test/System.Text/Latin1EncodingTest.cs b/mcs/class/corlib/Test/System.Text/Latin1EncodingTest.cs new file mode 100644 index 0000000000..0195967cd3 --- /dev/null +++ b/mcs/class/corlib/Test/System.Text/Latin1EncodingTest.cs @@ -0,0 +1,350 @@ +// +// Latin1EncodingTest.cs +// +// Author: +// Alexander Köplinger (alexander.koeplinger@xamarin.com) +// +// Copyright (C) 2016 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.Text; + +using NUnit.Framework; +using NUnit.Framework.Constraints; + +#if !MOBILE +using NUnit.Framework.SyntaxHelpers; +#endif + +namespace MonoTests.System.Text +{ + [TestFixture] + public class Latin1EncodingTest + { + private char[] testchars; + private byte[] testbytes; + + [SetUp] + public void SetUp () + { + testchars = new char[4]; + testchars[0] = 'T'; + testchars[1] = 'e'; + testchars[2] = 's'; + testchars[3] = 't'; + testbytes = new byte[4]; + testbytes[0] = (byte) 'T'; + testbytes[1] = (byte) 'e'; + testbytes[2] = (byte) 's'; + testbytes[3] = (byte) 't'; + } + + [Test] + public void IsBrowserDisplay () + { + Assert.IsTrue (Encoding.GetEncoding ("latin1").IsBrowserDisplay); + } + + [Test] + public void IsBrowserSave () + { + Assert.IsTrue (Encoding.GetEncoding ("latin1").IsBrowserSave); + } + + [Test] + public void IsMailNewsDisplay () + { + Assert.IsTrue (Encoding.GetEncoding ("latin1").IsMailNewsDisplay); + } + + [Test] + public void IsMailNewsSave () + { + Assert.IsTrue (Encoding.GetEncoding ("latin1").IsMailNewsSave); + } + + [Test] // Test GetBytes(char[]) + public void TestGetBytes1 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = latin1_encoding.GetBytes(testchars); + for (int i = 0; i < testchars.Length; i++) + Assert.AreEqual (testchars[i], (char) bytes[i]); + } + + [Test] // Test GetBytes(char[], int, int) + public void TestGetBytes2 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = latin1_encoding.GetBytes(testchars, 1, 1); + Assert.AreEqual (1, bytes.Length, "#1"); + Assert.AreEqual (testchars [1], (char) bytes [0], "#2"); + } + + [Test] // Test non-Latin1 char in char[] + public void TestGetBytes3 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + testchars[2] = (char) 0x100; + byte[] bytes = latin1_encoding.GetBytes(testchars); + Assert.AreEqual ('T', (char) bytes [0], "#1"); + Assert.AreEqual ('e', (char) bytes [1], "#2"); + Assert.AreEqual ('?', (char) bytes [2], "#3"); + Assert.AreEqual ('t', (char) bytes [3], "#4"); + } + + [Test] // Test GetBytes(char[], int, int, byte[], int) + public void TestGetBytes4 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = new Byte[1]; + int cnt = latin1_encoding.GetBytes(testchars, 1, 1, bytes, 0); + Assert.AreEqual (1, cnt, "#1"); + Assert.AreEqual (testchars [1], (char) bytes [0], "#2"); + } + + [Test] // Test GetBytes(string, int, int, byte[], int) + public void TestGetBytes5 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = new Byte[1]; + int cnt = latin1_encoding.GetBytes("Test", 1, 1, bytes, 0); + Assert.AreEqual ('e', (char) bytes [0], "#1"); + } + + [Test] // Test GetBytes(string) + public void TestGetBytes6 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = latin1_encoding.GetBytes("Test"); + for (int i = 0; i < testchars.Length; i++) + Assert.AreEqual (testchars [i], (char) bytes [i]); + } + + [Test] // Test GetBytes(string) + public void TestGetBytes7 () + { + var latin1_encoding = Encoding.GetEncoding ("latin1"); + + var expected = new byte [] { 0x3F, 0x20, 0x3F, 0x20, 0x3F }; + var actual = latin1_encoding.GetBytes("\u24c8 \u2075 \u221e"); // normal replacement + Assert.AreEqual (expected, actual, "#1"); + + expected = new byte [] { 0x3F, 0x3F }; + actual = latin1_encoding.GetBytes("\ud83d\ude0a"); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#2"); + + expected = new byte [] { 0x3F, 0x3F, 0x20 }; + actual = latin1_encoding.GetBytes("\ud83d\ude0a "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#3"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud83d\ude0a "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#4"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud834\udd1e "); // surrogate pair replacement + Assert.AreEqual (expected, actual, "#5"); + + expected = new byte [] { 0x41, 0x42, 0x43, 0x00, 0x41, 0x42, 0x43 }; + actual = latin1_encoding.GetBytes("ABC\0ABC"); // embedded zero byte not replaced + Assert.AreEqual (expected, actual, "#6"); + + expected = new byte [] { 0x20, 0x20, 0x3F, 0x20, 0x20 }; + actual = latin1_encoding.GetBytes(" \ud834 "); // invalid surrogate pair replacement + Assert.AreEqual (expected, actual, "#7"); + } + + [Test] // Test GetChars(byte[]) + public void TestGetChars1 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + char[] chars = latin1_encoding.GetChars(testbytes); + for (int i = 0; i < testbytes.Length; i++) + Assert.AreEqual (testbytes[i], (byte) chars[i]); + } + + [Test] // Test GetChars(byte[], int, int) + public void TestGetChars2 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + char[] chars = latin1_encoding.GetChars(testbytes, 1, 1); + Assert.AreEqual (1, chars.Length, "#1"); + Assert.AreEqual (testbytes [1], (byte) chars [0], "#2"); + } + + [Test] // Test GetChars(byte[], int, int, char[], int) + public void TestGetChars4 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + char[] chars = new char[1]; + int cnt = latin1_encoding.GetChars(testbytes, 1, 1, chars, 0); + Assert.AreEqual (1, cnt, "#1"); + Assert.AreEqual (testbytes [1], (byte) chars [0], "#2"); + } + + [Test] // Test GetString(char[]) + public void TestGetString1 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + string str = latin1_encoding.GetString(testbytes); + Assert.AreEqual ("Test", str); + } + + [Test] // Test GetString(char[], int, int) + public void TestGetString2 () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + string str = latin1_encoding.GetString(testbytes, 1, 2); + Assert.AreEqual ("es", str); + } + + [Test] // Test Decoder + public void TestDecoder () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + char[] chars = new char[1]; + int cnt = latin1_encoding.GetDecoder().GetChars(testbytes, 1, 1, chars, 0); + Assert.AreEqual (1, cnt, "#1"); + Assert.AreEqual (testbytes [1], (byte) chars [0], "#2"); + } + + [Test] // Test Decoder + public void TestEncoder () + { + Encoding latin1_encoding = Encoding.GetEncoding ("latin1"); + byte[] bytes = new Byte[1]; + int cnt = latin1_encoding.GetEncoder().GetBytes(testchars, 1, 1, bytes, 0, false); + Assert.AreEqual (1, cnt, "#1"); + Assert.AreEqual (testchars [1], (char) bytes [0], "#2"); + } + + [Test] + public void TestZero () + { + Encoding encoding = Encoding.GetEncoding ("latin1"); + Assert.AreEqual (string.Empty, encoding.GetString (new byte [0]), "#1"); + Assert.AreEqual (string.Empty, encoding.GetString (new byte [0], 0, 0), "#2"); + } + + [Test] + [ExpectedException (typeof (EncoderFallbackException))] + public void EncoderFallback () + { + Encoding e = Encoding.GetEncoding ("latin1").Clone () as Encoding; + e.EncoderFallback = new EncoderExceptionFallback (); + e.GetBytes ("\u24c8"); + } + + [Test] + // [ExpectedException (typeof (ArgumentException))] + public void DecoderFallback2 () + { + var bytes = new byte[] { + 0x30, 0xa0, 0x31, 0xa8 + }; + var enc = (Encoding)Encoding.GetEncoding ("latin1").Clone (); + enc.DecoderFallback = new TestFallbackDecoder (); + + var chars = new char [7]; + var ret = enc.GetChars (bytes, 0, bytes.Length, chars, 0); + Console.WriteLine (ret); + + for (int i = 0; i < chars.Length; i++) { + Console.Write ("{0:x2} ", (int)chars [i]); + } + Console.WriteLine (); + } + + [Test] + public void DecoderFallback3 () + { + var bytes = new byte[] { + 0x30, 0xa0, 0x31, 0xa8 + }; + var enc = (Encoding)Encoding.GetEncoding ("latin1").Clone (); + enc.DecoderFallback = new TestFallbackDecoder (); + + var chars = new char[] { '9', '8', '7', '6', '5' }; + var ret = enc.GetChars (bytes, 0, bytes.Length, chars, 0); + + Assert.That (ret, Is.EqualTo (4), "ret"); + Assert.That (chars [0], Is.EqualTo ('0'), "chars[0]"); + Assert.That (chars [1], Is.EqualTo ((char)0xA0), "chars[1]"); + Assert.That (chars [2], Is.EqualTo ('1'), "chars[2]"); + Assert.That (chars [3], Is.EqualTo ((char)0xA8), "chars[3]"); + Assert.That (chars [4], Is.EqualTo ('5'), "chars[4]"); + } + + class TestFallbackDecoder : DecoderFallback { + const int count = 2; + + public override int MaxCharCount { + get { return count; } + } + + public override DecoderFallbackBuffer CreateFallbackBuffer () + { + return new Buffer (); + } + + class Buffer : DecoderFallbackBuffer { + char[] queue; + int index; + + public override int Remaining { + get { + return queue.Length - index; + } + } + + public override char GetNextChar () + { + return index < queue.Length ? queue [index++] : '\0'; + } + + public override bool Fallback (byte[] bytes, int unused) + { + queue = new char[bytes.Length * count]; + index = 0; + for (int i = 0; i < bytes.Length; i++) { + for (int j = 0; j < count; j++) + queue [index++] = (char)(bytes [i]+j); + } + return true; + } + + public override bool MovePrevious () + { + throw new NotImplementedException (); + } + + public override void Reset () + { + base.Reset (); + } + } + } + + } +} diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 55a90d6257..f6eef5aa1a 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -615,7 +615,6 @@ System.Security/NamedPermissionSet.cs System.Security/PermissionBuilder.cs System.Security/PermissionSet.cs System.Security/PolicyLevelType.cs -System.Security/SafeAccessTokenHandle.cs System.Security/SecureString.cs System.Security/SecurityElement.cs System.Security/SecurityFrame.cs @@ -1393,6 +1392,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/security/attributes.cs ../referencesource/mscorlib/system/security/securitycontext.cs ../referencesource/mscorlib/system/security/securitydocument.cs +../referencesource/mscorlib/system/security/safesecurityhandles.cs ../referencesource/mscorlib/system/security/claims/Claim.cs ../referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs diff --git a/mcs/class/corlib/corlib_test.dll.sources b/mcs/class/corlib/corlib_test.dll.sources index 7dfe833f16..46f4d2752e 100644 --- a/mcs/class/corlib/corlib_test.dll.sources +++ b/mcs/class/corlib/corlib_test.dll.sources @@ -405,6 +405,7 @@ System.Text/EncoderTest.cs System.Text/EncodingTest.cs System.Text/EncodingTester.cs System.Text/EncodingInfoTest.cs +System.Text/Latin1EncodingTest.cs System.Text/StringBuilderTest.cs System.Text/TestEncoding.cs System.Text/UnicodeEncodingTest.cs diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs index 71341f5bc2..7da7303d75 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs @@ -501,6 +501,44 @@ namespace System.Dynamic { binder.ReturnType ); +#if MONO // referencesource version + Expression condition; + // If the return type can not be assigned null then just check for type assignablity otherwise allow null. + if (binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null) { + condition = Expression.TypeIs(resultMO.Expression, binder.ReturnType); + } + else { + condition = Expression.OrElse( + Expression.Equal(resultMO.Expression, Expression.Constant(null)), + Expression.TypeIs(resultMO.Expression, binder.ReturnType)); + } + + var checkedConvert = Expression.Condition( + condition, + convert, + Expression.Throw( + Expression.New(typeof(InvalidCastException).GetConstructor(new Type[]{typeof(string)}), + Expression.Call( + typeof(string).GetMethod("Format", new Type[] {typeof(string), typeof(object[])}), + Expression.Constant(convertFailed), + Expression.NewArrayInit(typeof(object), + Expression.Condition( + Expression.Equal(resultMO.Expression, Expression.Constant(null)), + Expression.Constant("null"), + Expression.Call( + resultMO.Expression, + typeof(object).GetMethod("GetType") + ), + typeof(object) + ) + ) + ) + ), + binder.ReturnType + ), + binder.ReturnType + ); +#else var checkedConvert = Expression.Condition( Expression.TypeIs(resultMO.Expression, binder.ReturnType), convert, @@ -524,6 +562,7 @@ namespace System.Dynamic { ), binder.ReturnType ); +#endif resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions); } diff --git a/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id index 693fd9ef18..9c2dbecc7d 100644 --- a/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id @@ -1 +1 @@ -0e58c3fba67bf21766014677b5f894f7637162d9 \ No newline at end of file +c490c7433c000c0ca9ff7be0753080941738fdbc \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.dll.REMOVED.git-id index 4df4775fe2..3b134fe279 100644 --- a/mcs/class/lib/monolite/System.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.dll.REMOVED.git-id @@ -1 +1 @@ -8ad53def268a4750474dee2731ef4039642458aa \ No newline at end of file +c3bbfb8e3d0bb1d4648a456800a8f616d8a28016 \ No newline at end of file diff --git a/mcs/class/lib/monolite/basic.exe.REMOVED.git-id b/mcs/class/lib/monolite/basic.exe.REMOVED.git-id index 695bcfdbfe..43e96dbad5 100644 --- a/mcs/class/lib/monolite/basic.exe.REMOVED.git-id +++ b/mcs/class/lib/monolite/basic.exe.REMOVED.git-id @@ -1 +1 @@ -4ed6e201e6785a6e9e44a113d2be4c9fd569673c \ No newline at end of file +8410f10f87dea9524681b3f688dab2f70afbf9b5 \ No newline at end of file diff --git a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id index 4629fff27b..2ecd925178 100644 --- a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id @@ -1 +1 @@ -9d728aa18a9d89c58a94469c86f374658f784ccd \ No newline at end of file +d2b12594e92c61982d88980ec4bfaeb7c3bdf9ab \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/security/safesecurityhandles.cs b/mcs/class/referencesource/mscorlib/system/security/safesecurityhandles.cs index 49adc58c26..8161a3be2a 100644 --- a/mcs/class/referencesource/mscorlib/system/security/safesecurityhandles.cs +++ b/mcs/class/referencesource/mscorlib/system/security/safesecurityhandles.cs @@ -38,7 +38,11 @@ namespace Microsoft.Win32.SafeHandles { [SecurityCritical] protected override bool ReleaseHandle() { +#if MONO + return true; +#else return Win32Native.CloseHandle(handle); +#endif } } diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs index 1c63e70b91..1915a07240 100644 --- a/mcs/mcs/cs-tokenizer.cs +++ b/mcs/mcs/cs-tokenizer.cs @@ -2562,6 +2562,9 @@ namespace Mono.CSharp pow /= 10; } } + } else if (c == '\n' || c == UnicodeLS || c == UnicodePS) { + advance_line (); + break; } else if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') { break; } @@ -2587,9 +2590,6 @@ namespace Mono.CSharp while (c == ' ' || c == '\t') c = get_char (); - if (c == '\n' || c == UnicodeLS || c == UnicodePS) - advance_line (); - return number; } diff --git a/mcs/tests/dtest-065.cs b/mcs/tests/dtest-065.cs new file mode 100644 index 0000000000..fb51a71dbf --- /dev/null +++ b/mcs/tests/dtest-065.cs @@ -0,0 +1,28 @@ +using System.Dynamic; + +public class TestConvert : DynamicObject +{ + public override bool TryConvert (ConvertBinder binder, out object result) + { + result = null; + return true; + } +} + +public class Test : DynamicObject +{ + public override bool TryInvokeMember (InvokeMemberBinder binder, object [] args, out object result) + { + result = new TestConvert (); + return true; + } +} + +public class XX +{ + public static void Main () + { + dynamic t = new Test (); + string result = t.SomeMethod (); + } +} \ No newline at end of file diff --git a/mcs/tests/test-debug-30-ref.xml b/mcs/tests/test-debug-30-ref.xml index 461f6573e5..34ed226553 100644 --- a/mcs/tests/test-debug-30-ref.xml +++ b/mcs/tests/test-debug-30-ref.xml @@ -1,7 +1,7 @@  - + @@ -27,5 +27,14 @@ + + + + + + \ No newline at end of file diff --git a/mcs/tests/test-debug-30.cs b/mcs/tests/test-debug-30.cs index 78f0cdfe3c..a72f014101 100644 --- a/mcs/tests/test-debug-30.cs +++ b/mcs/tests/test-debug-30.cs @@ -15,4 +15,12 @@ class PragmaNewLinesParsing { return; } + +#pragma warning disable 618 +#pragma warning restore 618 + + void OneMore () + { + return; + } } \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id b/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id index e7ea069d28..52d7c901c4 100644 --- a/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id +++ b/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id @@ -1 +1 @@ -720ef10c534ff81a6c9296b3f09a50987144d5a9 \ No newline at end of file +216a310da0866d4efac81f4c8a3bcdc849ad8891 \ No newline at end of file diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 579b93afc1..9b73ccd2bb 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -1927,6 +1927,20 @@ mono_domain_assembly_search (MonoAssemblyName *aname, return NULL; } +static gboolean +prevent_running_reference_assembly (MonoAssembly *ass, MonoError *error) +{ + mono_error_init (error); + gboolean refasm = mono_assembly_get_reference_assembly_attribute (ass, error); + if (!is_ok (error)) + return TRUE; + if (refasm) { + mono_error_set_bad_image (error, ass->image, "Could not load file or assembly or one of its dependencies. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.\n"); + return TRUE; + } + return FALSE; +} + MonoReflectionAssembly * ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean refOnly) { @@ -1935,37 +1949,40 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re MonoDomain *domain = mono_domain_get (); char *name, *filename; MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *ass; + MonoAssembly *ass = NULL; + + name = NULL; + result = NULL; + + mono_error_init (&error); if (fname == NULL) { - MonoException *exc = mono_get_exception_argument_null ("assemblyFile"); - mono_set_pending_exception (exc); - return NULL; + mono_error_set_argument_null (&error, "assemblyFile", ""); + goto leave; } name = filename = mono_string_to_utf8_checked (fname, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + if (!is_ok (&error)) + goto leave; ass = mono_assembly_open_full (filename, &status, refOnly); if (!ass) { - MonoException *exc; - if (status == MONO_IMAGE_IMAGE_INVALID) - exc = mono_get_exception_bad_image_format2 (NULL, fname); + mono_error_set_bad_image_name (&error, name, ""); else - exc = mono_get_exception_file_not_found2 (NULL, fname); - g_free (name); - mono_set_pending_exception (exc); - return NULL; + mono_error_set_exception_instance (&error, mono_get_exception_file_not_found2 (NULL, fname)); + goto leave; } - g_free (name); + if (!refOnly && prevent_running_reference_assembly (ass, &error)) + goto leave; result = mono_assembly_get_object_checked (domain, ass, &error); - if (!result) - mono_error_set_pending_exception (&error); + +leave: + mono_error_set_pending_exception (&error); + g_free (name); return result; } @@ -2000,6 +2017,11 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad, return NULL; } + if (!refonly && prevent_running_reference_assembly (ass, &error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + refass = mono_assembly_get_object_checked (domain, ass, &error); if (!refass) mono_error_set_pending_exception (&error); @@ -2017,7 +2039,7 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, MonoAssembly *ass; MonoAssemblyName aname; MonoReflectionAssembly *refass = NULL; - gchar *name; + gchar *name = NULL; gboolean parsed; g_assert (assRef); @@ -2026,16 +2048,13 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, if (mono_error_set_pending_exception (&error)) return NULL; parsed = mono_assembly_name_parse (name, &aname); - g_free (name); if (!parsed) { /* This is a parse error... */ if (!refOnly) { refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error); - if (!mono_error_ok (&error)) { - mono_error_set_pending_exception (&error); - return NULL; - } + if (!is_ok (&error)) + goto leave; } return refass; } @@ -2047,25 +2066,31 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */ if (!refOnly) { refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error); - if (!mono_error_ok (&error)) { - mono_error_set_pending_exception (&error); - return NULL; - } + if (!is_ok (&error)) + goto leave; } else refass = NULL; - if (!refass) { - return NULL; - } + if (!refass) + goto leave; + ass = refass->assembly; } - if (refass == NULL) - refass = mono_assembly_get_object_checked (domain, ass, &error); + if (!refOnly && prevent_running_reference_assembly (ass, &error)) + goto leave; - if (refass == NULL) - mono_error_set_pending_exception (&error); - else - MONO_OBJECT_SETREF (refass, evidence, evidence); + g_assert (ass); + if (refass == NULL) { + refass = mono_assembly_get_object_checked (domain, ass, &error); + if (!is_ok (&error)) + goto leave; + } + + MONO_OBJECT_SETREF (refass, evidence, evidence); + +leave: + g_free (name); + mono_error_set_pending_exception (&error); return refass; } diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c deleted file mode 100644 index 57ce86ba71..0000000000 --- a/mono/metadata/assembly.c +++ /dev/null @@ -1,3653 +0,0 @@ -/* - * assembly.c: Routines for loading assemblies. - * - * Author: - * Miguel de Icaza (miguel@ximian.com) - * - * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) - * Copyright 2004-2009 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 -#include -#include -#include -#include -#include -#include "assembly.h" -#include "image.h" -#include "object-internals.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef HOST_WIN32 -#include -#include -#include -#endif - -#ifdef PLATFORM_MACOSX -#include -#endif - -/* AssemblyVersionMap: an assembly name, the assembly version set on which it is based, the assembly name it is replaced with and whether only versions lower than the current runtime version should be remapped */ -typedef struct { - const char* assembly_name; - guint8 version_set_index; - const char* new_assembly_name; - gboolean only_lower_versions; -} AssemblyVersionMap; - -/* the default search path is empty, the first slot is replaced with the computed value */ -static const char* -default_path [] = { - NULL, - NULL, - NULL -}; - -/* Contains the list of directories to be searched for assemblies (MONO_PATH) */ -static char **assemblies_path = NULL; - -/* Contains the list of directories that point to auxiliary GACs */ -static char **extra_gac_paths = NULL; - -#ifndef DISABLE_ASSEMBLY_REMAPPING -/* The list of system assemblies what will be remapped to the running - * runtime version. WARNING: this list must be sorted. - * The integer number is an index in the MonoRuntimeInfo structure, whose - * values can be found in domain.c - supported_runtimes. Look there - * to understand what remapping will be made. - * - * .NET version can be found at https://github.com/dotnet/coreclr/blob/master/src/inc/fxretarget.h#L99 - * - */ -static const AssemblyVersionMap framework_assemblies [] = { - {"Accessibility", 0}, - {"Commons.Xml.Relaxng", 0}, - {"I18N", 0}, - {"I18N.CJK", 0}, - {"I18N.MidEast", 0}, - {"I18N.Other", 0}, - {"I18N.Rare", 0}, - {"I18N.West", 0}, - {"Microsoft.Build.Engine", 2, NULL, TRUE}, - {"Microsoft.Build.Framework", 2, NULL, TRUE}, - {"Microsoft.Build.Tasks", 2, "Microsoft.Build.Tasks.v4.0"}, - {"Microsoft.Build.Tasks.v3.5", 2, "Microsoft.Build.Tasks.v4.0"}, - {"Microsoft.Build.Utilities", 2, "Microsoft.Build.Utilities.v4.0"}, - {"Microsoft.Build.Utilities.v3.5", 2, "Microsoft.Build.Utilities.v4.0"}, - {"Microsoft.VisualBasic", 1}, - {"Microsoft.VisualC", 1}, - {"Mono.Cairo", 0}, - {"Mono.CompilerServices.SymbolWriter", 0}, - {"Mono.Data", 0}, - {"Mono.Data.SybaseClient", 0}, - {"Mono.Data.Tds", 0}, - {"Mono.Data.TdsClient", 0}, - {"Mono.GetOptions", 0}, - {"Mono.Http", 0}, - {"Mono.Posix", 0}, - {"Mono.Security", 0}, - {"Mono.Security.Win32", 0}, - {"Mono.Xml.Ext", 0}, - {"Novell.Directory.Ldap", 0}, - {"PEAPI", 0}, - {"System", 0}, - {"System.ComponentModel.Composition", 2}, - {"System.ComponentModel.DataAnnotations", 2}, - {"System.Configuration", 0}, - {"System.Configuration.Install", 0}, - {"System.Core", 2}, - {"System.Data", 0}, - {"System.Data.Linq", 2}, - {"System.Data.OracleClient", 0}, - {"System.Data.Services", 2}, - {"System.Data.Services.Client", 2}, - {"System.Data.SqlXml", 0}, - {"System.Design", 0}, - {"System.DirectoryServices", 0}, - {"System.Drawing", 0}, - {"System.Drawing.Design", 0}, - {"System.EnterpriseServices", 0}, - {"System.IdentityModel", 3}, - {"System.IdentityModel.Selectors", 3}, - {"System.Management", 0}, - {"System.Messaging", 0}, - {"System.Net", 2}, - {"System.Runtime.Remoting", 0}, - {"System.Runtime.Serialization", 3}, - {"System.Runtime.Serialization.Formatters.Soap", 0}, - {"System.Security", 0}, - {"System.ServiceModel", 3}, - {"System.ServiceModel.Web", 2}, - {"System.ServiceProcess", 0}, - {"System.Transactions", 0}, - {"System.Web", 0}, - {"System.Web.Abstractions", 2}, - {"System.Web.DynamicData", 2}, - {"System.Web.Extensions", 2}, - {"System.Web.Mobile", 0}, - {"System.Web.Routing", 2}, - {"System.Web.Services", 0}, - {"System.Windows.Forms", 0}, - {"System.Xml", 0}, - {"System.Xml.Linq", 2}, - {"WindowsBase", 3}, - {"mscorlib", 0} -}; -#endif - -/* - * keeps track of loaded assemblies - */ -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 */ -#define mono_assemblies_lock() mono_os_mutex_lock (&assemblies_mutex) -#define mono_assemblies_unlock() mono_os_mutex_unlock (&assemblies_mutex) -static mono_mutex_t assemblies_mutex; - -/* If defined, points to the bundled assembly information */ -const MonoBundledAssembly **bundles; - -static mono_mutex_t assembly_binding_mutex; - -/* Loaded assembly binding info */ -static GSList *loaded_assembly_bindings = NULL; - -/* Class lazy loading functions */ -static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute) - -static MonoAssembly* -mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload); -static MonoAssembly* -mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly); -static MonoBoolean -mono_assembly_is_in_gac (const gchar *filanem); - -static gchar* -encode_public_tok (const guchar *token, gint32 len) -{ - const static gchar allowed [] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - gchar *res; - int i; - - res = (gchar *)g_malloc (len * 2 + 1); - for (i = 0; i < len; i++) { - res [i * 2] = allowed [token [i] >> 4]; - res [i * 2 + 1] = allowed [token [i] & 0xF]; - } - res [len * 2] = 0; - return res; -} - -/** - * mono_public_tokens_are_equal: - * @pubt1: first public key token - * @pubt2: second public key token - * - * Compare two public key tokens and return #TRUE is they are equal and #FALSE - * otherwise. - */ -gboolean -mono_public_tokens_are_equal (const unsigned char *pubt1, const unsigned char *pubt2) -{ - return memcmp (pubt1, pubt2, 16) == 0; -} - -/** - * mono_set_assemblies_path: - * @path: list of paths that contain directories where Mono will look for assemblies - * - * Use this method to override the standard assembly lookup system and - * override any assemblies coming from the GAC. This is the method - * that supports the MONO_PATH variable. - * - * Notice that MONO_PATH and this method are really a very bad idea as - * it prevents the GAC from working and it prevents the standard - * resolution mechanisms from working. Nonetheless, for some debugging - * situations and bootstrapping setups, this is useful to have. - */ -void -mono_set_assemblies_path (const char* path) -{ - char **splitted, **dest; - - splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000); - if (assemblies_path) - g_strfreev (assemblies_path); - assemblies_path = dest = splitted; - while (*splitted) { - char *tmp = *splitted; - if (*tmp) - *dest++ = mono_path_canonicalize (tmp); - g_free (tmp); - splitted++; - } - *dest = *splitted; - - if (g_getenv ("MONO_DEBUG") == NULL) - return; - - splitted = assemblies_path; - while (*splitted) { - if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) - g_warning ("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *splitted); - - splitted++; - } -} - -/* 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) -{ - const char* path; - path = g_getenv ("MONO_PATH"); -#ifdef __native_client__ - if (!path) - path = nacl_mono_path; -#endif - if (!path || assemblies_path != NULL) - return; - - mono_set_assemblies_path(path); -} - -static void -check_extra_gac_path_env (void) { - const char *path; - char **splitted, **dest; - - path = g_getenv ("MONO_GAC_PREFIX"); - if (!path) - return; - - splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000); - if (extra_gac_paths) - g_strfreev (extra_gac_paths); - extra_gac_paths = dest = splitted; - while (*splitted){ - if (**splitted) - *dest++ = *splitted; - splitted++; - } - *dest = *splitted; - - if (g_getenv ("MONO_DEBUG") == NULL) - return; - - while (*splitted) { - if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) - g_warning ("'%s' in MONO_GAC_PREFIX doesn't exist or has wrong permissions.", *splitted); - - splitted++; - } -} - -static gboolean -assembly_binding_maps_name (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) -{ - if (!info || !info->name) - return FALSE; - - if (strcmp (info->name, aname->name)) - return FALSE; - - if (info->major != aname->major || info->minor != aname->minor) - return FALSE; - - if ((info->culture != NULL && info->culture [0]) != (aname->culture != NULL && aname->culture [0])) - return FALSE; - - if (info->culture && aname->culture && strcmp (info->culture, aname->culture)) - return FALSE; - - if (!mono_public_tokens_are_equal (info->public_key_token, aname->public_key_token)) - return FALSE; - - return TRUE; -} - -static void -mono_assembly_binding_info_free (MonoAssemblyBindingInfo *info) -{ - if (!info) - return; - - g_free (info->name); - g_free (info->culture); -} - -static void -get_publisher_policy_info (MonoImage *image, MonoAssemblyName *aname, MonoAssemblyBindingInfo *binding_info) -{ - MonoTableInfo *t; - guint32 cols [MONO_MANIFEST_SIZE]; - const gchar *filename; - gchar *subpath, *fullpath; - - t = &image->tables [MONO_TABLE_MANIFESTRESOURCE]; - /* MS Impl. accepts policy assemblies with more than - * one manifest resource, and only takes the first one */ - if (t->rows < 1) { - binding_info->is_valid = FALSE; - return; - } - - mono_metadata_decode_row (t, 0, cols, MONO_MANIFEST_SIZE); - if ((cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) != MONO_IMPLEMENTATION_FILE) { - binding_info->is_valid = FALSE; - return; - } - - filename = mono_metadata_string_heap (image, cols [MONO_MANIFEST_NAME]); - g_assert (filename != NULL); - - subpath = g_path_get_dirname (image->name); - fullpath = g_build_path (G_DIR_SEPARATOR_S, subpath, filename, NULL); - mono_config_parse_publisher_policy (fullpath, binding_info); - g_free (subpath); - g_free (fullpath); - - /* Define the optional elements/attributes before checking */ - if (!binding_info->culture) - binding_info->culture = g_strdup (""); - - /* Check that the most important elements/attributes exist */ - if (!binding_info->name || !binding_info->public_key_token [0] || !binding_info->has_old_version_bottom || - !binding_info->has_new_version || !assembly_binding_maps_name (binding_info, aname)) { - mono_assembly_binding_info_free (binding_info); - binding_info->is_valid = FALSE; - return; - } - - binding_info->is_valid = TRUE; -} - -static int -compare_versions (AssemblyVersionSet *v, MonoAssemblyName *aname) -{ - if (v->major > aname->major) - return 1; - else if (v->major < aname->major) - return -1; - - if (v->minor > aname->minor) - return 1; - else if (v->minor < aname->minor) - return -1; - - if (v->build > aname->build) - return 1; - else if (v->build < aname->build) - return -1; - - if (v->revision > aname->revision) - return 1; - else if (v->revision < aname->revision) - return -1; - - return 0; -} - -static gboolean -check_policy_versions (MonoAssemblyBindingInfo *info, MonoAssemblyName *name) -{ - if (!info->is_valid) - return FALSE; - - /* If has_old_version_top doesn't exist, we don't have an interval */ - if (!info->has_old_version_top) { - if (compare_versions (&info->old_version_bottom, name) == 0) - return TRUE; - - return FALSE; - } - - /* Check that the version defined by name is valid for the interval */ - if (compare_versions (&info->old_version_top, name) < 0) - return FALSE; - - /* We should be greater or equal than the small version */ - if (compare_versions (&info->old_version_bottom, name) > 0) - return FALSE; - - return TRUE; -} - -/** - * mono_assembly_names_equal: - * @l: first assembly - * @r: second assembly. - * - * Compares two MonoAssemblyNames and returns whether they are equal. - * - * This compares the names, the cultures, the release version and their - * public tokens. - * - * Returns: TRUE if both assembly names are equal. - */ -gboolean -mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r) -{ - if (!l->name || !r->name) - return FALSE; - - if (strcmp (l->name, r->name)) - return FALSE; - - if (l->culture && r->culture && strcmp (l->culture, r->culture)) - return FALSE; - - if (l->major != r->major || l->minor != r->minor || - l->build != r->build || l->revision != r->revision) - if (! ((l->major == 0 && l->minor == 0 && l->build == 0 && l->revision == 0) || (r->major == 0 && r->minor == 0 && r->build == 0 && r->revision == 0))) - return FALSE; - - if (!l->public_key_token [0] || !r->public_key_token [0]) - return TRUE; - - if (!mono_public_tokens_are_equal (l->public_key_token, r->public_key_token)) - return FALSE; - - return TRUE; -} - -static MonoAssembly * -load_in_path (const char *basename, const char** search_path, MonoImageOpenStatus *status, MonoBoolean refonly) -{ - int i; - char *fullpath; - MonoAssembly *result; - - for (i = 0; search_path [i]; ++i) { - fullpath = g_build_filename (search_path [i], basename, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - if (result) - return result; - } - return NULL; -} - -/** - * mono_assembly_setrootdir: - * @root_dir: The pathname of the root directory where we will locate assemblies - * - * This routine sets the internal default root directory for looking up - * assemblies. - * - * This is used by Windows installations to compute dynamically the - * place where the Mono assemblies are located. - * - */ -void -mono_assembly_setrootdir (const char *root_dir) -{ - /* - * Override the MONO_ASSEMBLIES directory configured at compile time. - */ - /* Leak if called more than once */ - default_path [0] = g_strdup (root_dir); -} - -/** - * mono_assembly_getrootdir: - * - * Obtains the root directory used for looking up assemblies. - * - * Returns: a string with the directory, this string should not be freed. - */ -G_CONST_RETURN gchar * -mono_assembly_getrootdir (void) -{ - return default_path [0]; -} - -/** - * mono_set_dirs: - * @assembly_dir: the base directory for assemblies - * @config_dir: the base directory for configuration files - * - * This routine is used internally and by developers embedding - * the runtime into their own applications. - * - * There are a number of cases to consider: Mono as a system-installed - * package that is available on the location preconfigured or Mono in - * a relocated location. - * - * If you are using a system-installed Mono, you can pass NULL - * to both parameters. If you are not, you should compute both - * directory values and call this routine. - * - * The values for a given PREFIX are: - * - * assembly_dir: PREFIX/lib - * config_dir: PREFIX/etc - * - * Notice that embedders that use Mono in a relocated way must - * compute the location at runtime, as they will be in control - * of where Mono is installed. - */ -void -mono_set_dirs (const char *assembly_dir, const char *config_dir) -{ - if (assembly_dir == NULL) - assembly_dir = mono_config_get_assemblies_dir (); - if (config_dir == NULL) - config_dir = mono_config_get_cfg_dir (); - mono_assembly_setrootdir (assembly_dir); - mono_set_config_dir (config_dir); -} - -#ifndef HOST_WIN32 - -static char * -compute_base (char *path) -{ - char *p = strrchr (path, '/'); - if (p == NULL) - return NULL; - - /* Not a well known Mono executable, we are embedded, cant guess the base */ - if (strcmp (p, "/mono") && strcmp (p, "/mono-boehm") && strcmp (p, "/mono-sgen") && strcmp (p, "/pedump") && strcmp (p, "/monodis")) - return NULL; - - *p = 0; - p = strrchr (path, '/'); - if (p == NULL) - return NULL; - - if (strcmp (p, "/bin") != 0) - return NULL; - *p = 0; - return path; -} - -static void -fallback (void) -{ - mono_set_dirs (mono_config_get_assemblies_dir (), mono_config_get_cfg_dir ()); -} - -static G_GNUC_UNUSED void -set_dirs (char *exe) -{ - char *base; - char *config, *lib, *mono; - struct stat buf; - const char *bindir; - - /* - * Only /usr prefix is treated specially - */ - bindir = mono_config_get_bin_dir (); - g_assert (bindir); - if (strncmp (exe, bindir, strlen (bindir)) == 0 || (base = compute_base (exe)) == NULL){ - fallback (); - return; - } - - config = g_build_filename (base, "etc", NULL); - lib = g_build_filename (base, "lib", NULL); - mono = g_build_filename (lib, "mono/4.5", NULL); // FIXME: stop hardcoding 4.5 here - if (stat (mono, &buf) == -1) - fallback (); - else { - mono_set_dirs (lib, config); - } - - g_free (config); - g_free (lib); - g_free (mono); -} - -#endif /* HOST_WIN32 */ - -/** - * mono_set_rootdir: - * - * Registers the root directory for the Mono runtime, for Linux and Solaris 10, - * this auto-detects the prefix where Mono was installed. - */ -void -mono_set_rootdir (void) -{ -#if defined(HOST_WIN32) || (defined(PLATFORM_MACOSX) && !defined(TARGET_ARM)) - gchar *bindir, *installdir, *root, *name, *resolvedname, *config; - -#ifdef HOST_WIN32 - name = mono_get_module_file_name ((HMODULE) &__ImageBase); -#else - { - /* - * _NSGetExecutablePath may return -1 to indicate buf is not large - * enough, but we ignore that case to avoid having to do extra dynamic - * allocation for the path and hope that 4096 is enough - this is - * ok in the Linux/Solaris case below at least... - */ - - gchar buf[4096]; - guint buf_size = sizeof (buf); - - name = NULL; - if (_NSGetExecutablePath (buf, &buf_size) == 0) - name = g_strdup (buf); - - if (name == NULL) { - fallback (); - return; - } - } -#endif - - resolvedname = mono_path_resolve_symlinks (name); - - bindir = g_path_get_dirname (resolvedname); - installdir = g_path_get_dirname (bindir); - root = g_build_path (G_DIR_SEPARATOR_S, installdir, "lib", NULL); - - config = g_build_filename (root, "..", "etc", NULL); -#ifdef HOST_WIN32 - mono_set_dirs (root, config); -#else - if (g_file_test (root, G_FILE_TEST_EXISTS) && g_file_test (config, G_FILE_TEST_EXISTS)) - mono_set_dirs (root, config); - else - fallback (); -#endif - - g_free (config); - g_free (root); - g_free (installdir); - g_free (bindir); - g_free (name); - g_free (resolvedname); -#elif defined(DISABLE_MONO_AUTODETECTION) - fallback (); -#else - char buf [4096]; - int s; - char *str; - - /* Linux style */ - s = readlink ("/proc/self/exe", buf, sizeof (buf)-1); - - if (s != -1){ - buf [s] = 0; - set_dirs (buf); - return; - } - - /* Solaris 10 style */ - str = g_strdup_printf ("/proc/%d/path/a.out", getpid ()); - s = readlink (str, buf, sizeof (buf)-1); - g_free (str); - if (s != -1){ - buf [s] = 0; - set_dirs (buf); - return; - } - fallback (); -#endif -} - -/** - * mono_assemblies_init: - * - * Initialize global variables used by this module. - */ -void -mono_assemblies_init (void) -{ - /* - * Initialize our internal paths if we have not been initialized yet. - * This happens when embedders use Mono. - */ - if (mono_assembly_getrootdir () == NULL) - mono_set_rootdir (); - - check_path_env (); - check_extra_gac_path_env (); - - mono_os_mutex_init_recursive (&assemblies_mutex); - mono_os_mutex_init (&assembly_binding_mutex); -} - -static void -mono_assembly_binding_lock (void) -{ - mono_locks_os_acquire (&assembly_binding_mutex, AssemblyBindingLock); -} - -static void -mono_assembly_binding_unlock (void) -{ - mono_locks_os_release (&assembly_binding_mutex, AssemblyBindingLock); -} - -gboolean -mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname) -{ - MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY]; - guint32 cols [MONO_ASSEMBLY_SIZE]; - gint32 machine, flags; - - if (!t->rows) - return FALSE; - - mono_metadata_decode_row (t, 0, cols, MONO_ASSEMBLY_SIZE); - - aname->hash_len = 0; - aname->hash_value = NULL; - aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]); - aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_CULTURE]); - aname->flags = cols [MONO_ASSEMBLY_FLAGS]; - aname->major = cols [MONO_ASSEMBLY_MAJOR_VERSION]; - aname->minor = cols [MONO_ASSEMBLY_MINOR_VERSION]; - aname->build = cols [MONO_ASSEMBLY_BUILD_NUMBER]; - aname->revision = cols [MONO_ASSEMBLY_REV_NUMBER]; - aname->hash_alg = cols [MONO_ASSEMBLY_HASH_ALG]; - if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) { - guchar* token = (guchar *)g_malloc (8); - gchar* encoded; - const gchar* pkey; - int len; - - pkey = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]); - len = mono_metadata_decode_blob_size (pkey, &pkey); - aname->public_key = (guchar*)pkey; - - mono_digest_get_public_token (token, aname->public_key, len); - encoded = encode_public_tok (token, 8); - g_strlcpy ((char*)aname->public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH); - - g_free (encoded); - g_free (token); - } - else { - aname->public_key = NULL; - memset (aname->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } - - if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) { - aname->public_key = (guchar*)mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]); - } - else - aname->public_key = 0; - - machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine; - flags = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags; - switch (machine) { - case COFF_MACHINE_I386: - /* https://bugzilla.xamarin.com/show_bug.cgi?id=17632 */ - if (flags & (CLI_FLAGS_32BITREQUIRED|CLI_FLAGS_PREFERRED32BIT)) - aname->arch = MONO_PROCESSOR_ARCHITECTURE_X86; - else if ((flags & 0x70) == 0x70) - aname->arch = MONO_PROCESSOR_ARCHITECTURE_NONE; - else - aname->arch = MONO_PROCESSOR_ARCHITECTURE_MSIL; - break; - case COFF_MACHINE_IA64: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_IA64; - break; - case COFF_MACHINE_AMD64: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_AMD64; - break; - case COFF_MACHINE_ARM: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_ARM; - break; - default: - break; - } - - return TRUE; -} - -/** - * mono_stringify_assembly_name: - * @aname: the assembly name. - * - * Convert @aname into its string format. The returned string is dynamically - * allocated and should be freed by the caller. - * - * Returns: a newly allocated string with a string representation of - * the assembly name. - */ -char* -mono_stringify_assembly_name (MonoAssemblyName *aname) -{ - const char *quote = (aname->name && g_ascii_isspace (aname->name [0])) ? "\"" : ""; - - return g_strdup_printf ( - "%s%s%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", - quote, aname->name, quote, - aname->major, aname->minor, aname->build, aname->revision, - aname->culture && *aname->culture? aname->culture: "neutral", - aname->public_key_token [0] ? (char *)aname->public_key_token : "null", - (aname->flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : ""); -} - -static gchar* -assemblyref_public_tok (MonoImage *image, guint32 key_index, guint32 flags) -{ - const gchar *public_tok; - int len; - - public_tok = mono_metadata_blob_heap (image, key_index); - len = mono_metadata_decode_blob_size (public_tok, &public_tok); - - if (flags & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG) { - guchar token [8]; - mono_digest_get_public_token (token, (guchar*)public_tok, len); - return encode_public_tok (token, 8); - } - - return encode_public_tok ((guchar*)public_tok, len); -} - -/** - * mono_assembly_addref: - * @assemnly: the assembly to reference - * - * This routine increments the reference count on a MonoAssembly. - * The reference count is reduced every time the method mono_assembly_close() is - * invoked. - */ -void -mono_assembly_addref (MonoAssembly *assembly) -{ - InterlockedIncrement (&assembly->ref_count); -} - -/* - * CAUTION: This table must be kept in sync with - * ivkm/reflect/Fusion.cs - */ - -#define SILVERLIGHT_KEY "7cec85d7bea7798e" -#define WINFX_KEY "31bf3856ad364e35" -#define ECMA_KEY "b77a5c561934e089" -#define MSFINAL_KEY "b03f5f7f11d50a3a" - -typedef struct { - const char *name; - const char *from; - const char *to; -} KeyRemapEntry; - -static KeyRemapEntry key_remap_table[] = { - { "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY }, - { "System", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY }, - { "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY }, - { "System.Core", SILVERLIGHT_KEY, ECMA_KEY }, - // FIXME: MS uses MSFINAL_KEY for .NET 4.5 - { "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY }, - { "System.Numerics", WINFX_KEY, ECMA_KEY }, - { "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.ServiceModel", WINFX_KEY, ECMA_KEY }, - { "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY }, - { "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY }, - { "System.Xml", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.Xml.Linq", WINFX_KEY, ECMA_KEY }, - { "System.Xml.Serialization", WINFX_KEY, ECMA_KEY } -}; - -static void -remap_keys (MonoAssemblyName *aname) -{ - int i; - for (i = 0; i < G_N_ELEMENTS (key_remap_table); i++) { - const KeyRemapEntry *entry = &key_remap_table [i]; - - if (strcmp (aname->name, entry->name) || - !mono_public_tokens_are_equal (aname->public_key_token, (const unsigned char*) entry->from)) - continue; - - memcpy (aname->public_key_token, entry->to, MONO_PUBLIC_KEY_TOKEN_LENGTH); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Remapped public key token of retargetable assembly %s from %s to %s", - aname->name, entry->from, entry->to); - return; - } -} - -static MonoAssemblyName * -mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname) -{ - const MonoRuntimeInfo *current_runtime; - int pos, first, last; - - if (aname->name == NULL) return aname; - - current_runtime = mono_get_runtime_info (); - - if (aname->flags & ASSEMBLYREF_RETARGETABLE_FLAG) { - const AssemblyVersionSet* vset; - - /* Remap to current runtime */ - vset = ¤t_runtime->version_sets [0]; - - memcpy (dest_aname, aname, sizeof(MonoAssemblyName)); - dest_aname->major = vset->major; - dest_aname->minor = vset->minor; - dest_aname->build = vset->build; - dest_aname->revision = vset->revision; - dest_aname->flags &= ~ASSEMBLYREF_RETARGETABLE_FLAG; - - /* Remap assembly name */ - if (!strcmp (aname->name, "System.Net")) - dest_aname->name = g_strdup ("System"); - - remap_keys (dest_aname); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "The request to load the retargetable assembly %s v%d.%d.%d.%d was remapped to %s v%d.%d.%d.%d", - aname->name, - aname->major, aname->minor, aname->build, aname->revision, - dest_aname->name, - vset->major, vset->minor, vset->build, vset->revision - ); - - return dest_aname; - } - -#ifndef DISABLE_ASSEMBLY_REMAPPING - first = 0; - last = G_N_ELEMENTS (framework_assemblies) - 1; - - while (first <= last) { - int res; - pos = first + (last - first) / 2; - res = strcmp (aname->name, framework_assemblies[pos].assembly_name); - if (res == 0) { - const AssemblyVersionSet* vset; - int index = framework_assemblies[pos].version_set_index; - g_assert (index < G_N_ELEMENTS (current_runtime->version_sets)); - vset = ¤t_runtime->version_sets [index]; - - if (aname->major == vset->major && aname->minor == vset->minor && - aname->build == vset->build && aname->revision == vset->revision) - return aname; - - if (framework_assemblies[pos].only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0) - return aname; - - if ((aname->major | aname->minor | aname->build | aname->revision) != 0) - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, - "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d", - aname->name, - aname->major, aname->minor, aname->build, aname->revision, - vset->major, vset->minor, vset->build, vset->revision - ); - - memcpy (dest_aname, aname, sizeof(MonoAssemblyName)); - dest_aname->major = vset->major; - dest_aname->minor = vset->minor; - dest_aname->build = vset->build; - dest_aname->revision = vset->revision; - if (framework_assemblies[pos].new_assembly_name != NULL) { - dest_aname->name = framework_assemblies[pos].new_assembly_name; - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, - "The assembly name %s was remapped to %s", - aname->name, - dest_aname->name); - } - return dest_aname; - } else if (res < 0) { - last = pos - 1; - } else { - first = pos + 1; - } - } -#endif - - return aname; -} - -/** - * mono_assembly_get_assemblyref: - * @image: pointer to the MonoImage to extract the information from. - * @index: index to the assembly reference in the image. - * @aname: pointer to a `MonoAssemblyName` that will hold the returned value. - * - * Fills out the @aname with the assembly name of the @index assembly reference in @image. - */ -void -mono_assembly_get_assemblyref (MonoImage *image, int index, MonoAssemblyName *aname) -{ - MonoTableInfo *t; - guint32 cols [MONO_ASSEMBLYREF_SIZE]; - const char *hash; - - t = &image->tables [MONO_TABLE_ASSEMBLYREF]; - - mono_metadata_decode_row (t, index, cols, MONO_ASSEMBLYREF_SIZE); - - hash = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_HASH_VALUE]); - aname->hash_len = mono_metadata_decode_blob_size (hash, &hash); - aname->hash_value = hash; - aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME]); - aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]); - aname->flags = cols [MONO_ASSEMBLYREF_FLAGS]; - aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION]; - aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION]; - aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER]; - aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER]; - - if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) { - gchar *token = assemblyref_public_tok (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY], aname->flags); - g_strlcpy ((char*)aname->public_key_token, token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (token); - } else { - memset (aname->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } -} - -void -mono_assembly_load_reference (MonoImage *image, int index) -{ - MonoAssembly *reference; - MonoAssemblyName aname; - MonoImageOpenStatus status; - - /* - * image->references is shared between threads, so we need to access - * it inside a critical section. - */ - mono_assemblies_lock (); - if (!image->references) { - MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF]; - - image->references = g_new0 (MonoAssembly *, t->rows + 1); - image->nreferences = t->rows; - } - reference = image->references [index]; - mono_assemblies_unlock (); - if (reference) - return; - - mono_assembly_get_assemblyref (image, index, &aname); - - if (image->assembly && image->assembly->ref_only) { - /* We use the loaded corlib */ - if (!strcmp (aname.name, "mscorlib")) - reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE); - else { - reference = mono_assembly_loaded_full (&aname, TRUE); - if (!reference) - /* Try a postload search hook */ - reference = mono_assembly_invoke_search_hook_internal (&aname, image->assembly, TRUE, TRUE); - } - - /* - * Here we must advice that the error was due to - * a non loaded reference using the ReflectionOnly api - */ - if (!reference) - reference = (MonoAssembly *)REFERENCE_MISSING; - } else { - /* we first try without setting the basedir: this can eventually result in a ResolveAssembly - * event which is the MS .net compatible behaviour (the assemblyresolve_event3.cs test has been fixed - * accordingly, it would fail on the MS runtime before). - * The second load attempt has the basedir set to keep compatibility with the old mono behavior, for - * example bug-349190.2.cs and who knows how much more code in the wild. - */ - reference = mono_assembly_load_full_internal (&aname, image->assembly, NULL, &status, FALSE); - if (!reference && image->assembly) - reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE); - } - - if (reference == NULL){ - char *extra_msg; - - if (status == MONO_IMAGE_ERROR_ERRNO && errno == ENOENT) { - extra_msg = g_strdup_printf ("The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (%s).\n", image->assembly != NULL ? image->assembly->basedir : "" ); - } else if (status == MONO_IMAGE_ERROR_ERRNO) { - extra_msg = g_strdup_printf ("System error: %s\n", strerror (errno)); - } else if (status == MONO_IMAGE_MISSING_ASSEMBLYREF) { - extra_msg = g_strdup ("Cannot find an assembly referenced from this one.\n"); - } else if (status == MONO_IMAGE_IMAGE_INVALID) { - extra_msg = g_strdup ("The file exists but is not a valid assembly.\n"); - } else { - extra_msg = g_strdup (""); - } - - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following assembly referenced from %s could not be loaded:\n" - " Assembly: %s (assemblyref_index=%d)\n" - " Version: %d.%d.%d.%d\n" - " Public Key: %s\n%s", - image->name, aname.name, index, - aname.major, aname.minor, aname.build, aname.revision, - strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg); - g_free (extra_msg); - } - - mono_assemblies_lock (); - if (reference == NULL) { - /* Flag as not found */ - reference = (MonoAssembly *)REFERENCE_MISSING; - } - - if (!image->references [index]) { - if (reference != REFERENCE_MISSING){ - mono_assembly_addref (reference); - if (image->assembly) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Ref addref %s[%p] -> %s[%p]: %d", - image->assembly->aname.name, image->assembly, reference->aname.name, reference, reference->ref_count); - } else { - if (image->assembly) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p]\n", - image->assembly->aname.name, image->assembly); - } - - image->references [index] = reference; - } - mono_assemblies_unlock (); - - if (image->references [index] != reference) { - /* Somebody loaded it before us */ - mono_assembly_close (reference); - } -} - -/** - * mono_assembly_load_references: - * @image: - * @status: - * @deprecated: There is no reason to use this method anymore, it does nothing - * - * This method is now a no-op, it does nothing other than setting the @status to #MONO_IMAGE_OK - */ -void -mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status) -{ - /* This is a no-op now but it is part of the embedding API so we can't remove it */ - *status = MONO_IMAGE_OK; -} - -typedef struct AssemblyLoadHook AssemblyLoadHook; -struct AssemblyLoadHook { - AssemblyLoadHook *next; - MonoAssemblyLoadFunc func; - gpointer user_data; -}; - -AssemblyLoadHook *assembly_load_hook = NULL; - -void -mono_assembly_invoke_load_hook (MonoAssembly *ass) -{ - AssemblyLoadHook *hook; - - for (hook = assembly_load_hook; hook; hook = hook->next) { - hook->func (ass, hook->user_data); - } -} - -void -mono_install_assembly_load_hook (MonoAssemblyLoadFunc func, gpointer user_data) -{ - AssemblyLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_load_hook; - assembly_load_hook = hook; -} - -static void -free_assembly_load_hooks (void) -{ - AssemblyLoadHook *hook, *next; - - for (hook = assembly_load_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -typedef struct AssemblySearchHook AssemblySearchHook; -struct AssemblySearchHook { - AssemblySearchHook *next; - MonoAssemblySearchFunc func; - gboolean refonly; - gboolean postload; - gpointer user_data; -}; - -AssemblySearchHook *assembly_search_hook = NULL; - -static MonoAssembly* -mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload) -{ - AssemblySearchHook *hook; - - for (hook = assembly_search_hook; hook; hook = hook->next) { - if ((hook->refonly == refonly) && (hook->postload == postload)) { - MonoAssembly *ass; - /** - * A little explanation is in order here. - * - * The default postload search hook needs to know the requesting assembly to report it to managed code. - * The embedding API exposes a search hook that doesn't take such argument. - * - * The original fix would call the default search hook before all the registered ones and pass - * the requesting assembly to it. It works but broke a very suddle embedding API aspect that some users - * rely on. Which is the ordering between user hooks and the default runtime hook. - * - * Registering the hook after mono_jit_init would let your hook run before the default one and - * when using it to handle non standard app layouts this could save your app from a massive amount - * of syscalls that the default hook does when probing all sorts of places. Slow targets with horrible IO - * are all using this trick and if we broke this assumption they would be very disapointed at us. - * - * So what's the fix? We register the default hook using regular means and special case it when iterating - * over the registered hooks. This preserves ordering and enables managed resolve hooks to get the requesting - * assembly. - */ - if (hook->func == (void*)mono_domain_assembly_postload_search) - ass = mono_domain_assembly_postload_search (aname, requesting, refonly); - else - ass = hook->func (aname, hook->user_data); - if (ass) - return ass; - } - } - - return NULL; -} - -MonoAssembly* -mono_assembly_invoke_search_hook (MonoAssemblyName *aname) -{ - return mono_assembly_invoke_search_hook_internal (aname, NULL, FALSE, FALSE); -} - -static void -mono_install_assembly_search_hook_internal (MonoAssemblySearchFunc func, gpointer user_data, gboolean refonly, gboolean postload) -{ - AssemblySearchHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblySearchHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->refonly = refonly; - hook->postload = postload; - hook->next = assembly_search_hook; - assembly_search_hook = hook; -} - -void -mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, FALSE, FALSE); -} - -static void -free_assembly_search_hooks (void) -{ - AssemblySearchHook *hook, *next; - - for (hook = assembly_search_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -void -mono_install_assembly_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, TRUE, FALSE); -} - -void -mono_install_assembly_postload_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, FALSE, TRUE); -} - -void -mono_install_assembly_postload_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, TRUE, TRUE); -} - -typedef struct AssemblyPreLoadHook AssemblyPreLoadHook; -struct AssemblyPreLoadHook { - AssemblyPreLoadHook *next; - MonoAssemblyPreLoadFunc func; - gpointer user_data; -}; - -static AssemblyPreLoadHook *assembly_preload_hook = NULL; -static AssemblyPreLoadHook *assembly_refonly_preload_hook = NULL; - -static MonoAssembly * -invoke_assembly_preload_hook (MonoAssemblyName *aname, gchar **assemblies_path) -{ - AssemblyPreLoadHook *hook; - MonoAssembly *assembly; - - for (hook = assembly_preload_hook; hook; hook = hook->next) { - assembly = hook->func (aname, assemblies_path, hook->user_data); - if (assembly != NULL) - return assembly; - } - - return NULL; -} - -static MonoAssembly * -invoke_assembly_refonly_preload_hook (MonoAssemblyName *aname, gchar **assemblies_path) -{ - AssemblyPreLoadHook *hook; - MonoAssembly *assembly; - - for (hook = assembly_refonly_preload_hook; hook; hook = hook->next) { - assembly = hook->func (aname, assemblies_path, hook->user_data); - if (assembly != NULL) - return assembly; - } - - return NULL; -} - -void -mono_install_assembly_preload_hook (MonoAssemblyPreLoadFunc func, gpointer user_data) -{ - AssemblyPreLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyPreLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_preload_hook; - assembly_preload_hook = hook; -} - -void -mono_install_assembly_refonly_preload_hook (MonoAssemblyPreLoadFunc func, gpointer user_data) -{ - AssemblyPreLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyPreLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_refonly_preload_hook; - assembly_refonly_preload_hook = hook; -} - -static void -free_assembly_preload_hooks (void) -{ - AssemblyPreLoadHook *hook, *next; - - for (hook = assembly_preload_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } - - for (hook = assembly_refonly_preload_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -static gchar * -absolute_dir (const gchar *filename) -{ - gchar *cwd; - gchar *mixed; - gchar **parts; - gchar *part; - GList *list, *tmp; - GString *result; - gchar *res; - gint i; - - if (g_path_is_absolute (filename)) { - part = g_path_get_dirname (filename); - res = g_strconcat (part, G_DIR_SEPARATOR_S, NULL); - g_free (part); - return res; - } - - cwd = g_get_current_dir (); - mixed = g_build_filename (cwd, filename, NULL); - parts = g_strsplit (mixed, G_DIR_SEPARATOR_S, 0); - g_free (mixed); - g_free (cwd); - - list = NULL; - for (i = 0; (part = parts [i]) != NULL; i++) { - if (!strcmp (part, ".")) - continue; - - if (!strcmp (part, "..")) { - if (list && list->next) /* Don't remove root */ - list = g_list_delete_link (list, list); - } else { - list = g_list_prepend (list, part); - } - } - - result = g_string_new (""); - list = g_list_reverse (list); - - /* Ignores last data pointer, which should be the filename */ - for (tmp = list; tmp && tmp->next != NULL; tmp = tmp->next){ - if (tmp->data) - g_string_append_printf (result, "%s%c", (char *) tmp->data, - G_DIR_SEPARATOR); - } - - res = result->str; - g_string_free (result, FALSE); - g_list_free (list); - g_strfreev (parts); - if (*res == '\0') { - g_free (res); - return g_strdup ("."); - } - - return res; -} - -/** - * mono_assembly_open_from_bundle: - * @filename: Filename requested - * @status: return status code - * - * This routine tries to open the assembly specified by `filename' from the - * defined bundles, if found, returns the MonoImage for it, if not found - * returns NULL - */ -MonoImage * -mono_assembly_open_from_bundle (const char *filename, MonoImageOpenStatus *status, gboolean refonly) -{ - int i; - char *name; - MonoImage *image = NULL; - - /* - * we do a very simple search for bundled assemblies: it's not a general - * purpose assembly loading mechanism. - */ - - if (!bundles) - return NULL; - - name = g_path_get_basename (filename); - - mono_assemblies_lock (); - for (i = 0; !image && bundles [i]; ++i) { - if (strcmp (bundles [i]->name, name) == 0) { - image = mono_image_open_from_data_with_name ((char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, name); - break; - } - } - mono_assemblies_unlock (); - if (image) { - mono_image_addref (image); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Loader loaded assembly from bundle: '%s'.", name); - g_free (name); - return image; - } - g_free (name); - return NULL; -} - -/** - * mono_assemblies_open_full: - * @filename: the file to load - * @status: return status code - * @refonly: Whether this assembly is being opened in "reflection-only" mode. -* - * This loads an assembly from the specified @filename. The @filename allows - * a local URL (starting with a file:// prefix). If a file prefix is used, the - * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file - * is treated as a local path. - * - * First, an attempt is made to load the assembly from the bundled executable (for those - * deployments that have been done with the `mkbundle` tool or for scenarios where the - * assembly has been registered as an embedded assembly). If this is not the case, then - * the assembly is loaded from disk using `api:mono_image_open_full`. - * - * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of - * the assembly is made. - * - * If @refonly is set to true, then the assembly is loaded purely for inspection with - * the `System.Reflection` API. - * - * Returns: NULL on error, with the @status set to an error code, or a pointer - * to the assembly. - */ -MonoAssembly * -mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboolean refonly) -{ - MonoImage *image; - MonoAssembly *ass; - MonoImageOpenStatus def_status; - gchar *fname; - gchar *new_fname; - gboolean loaded_from_bundle; - - g_return_val_if_fail (filename != NULL, NULL); - - if (!status) - status = &def_status; - *status = MONO_IMAGE_OK; - - if (strncmp (filename, "file://", 7) == 0) { - GError *error = NULL; - gchar *uri = (gchar *) filename; - gchar *tmpuri; - - /* - * MS allows file://c:/... and fails on file://localhost/c:/... - * They also throw an IndexOutOfRangeException if "file://" - */ - if (uri [7] != '/') - uri = g_strdup_printf ("file:///%s", uri + 7); - - tmpuri = uri; - uri = mono_escape_uri_string (tmpuri); - fname = g_filename_from_uri (uri, NULL, &error); - g_free (uri); - - if (tmpuri != filename) - g_free (tmpuri); - - if (error != NULL) { - g_warning ("%s\n", error->message); - g_error_free (error); - fname = g_strdup (filename); - } - } else { - fname = g_strdup (filename); - } - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader probing location: '%s'.", fname); - - new_fname = NULL; - if (!mono_assembly_is_in_gac (fname)) { - MonoError error; - new_fname = mono_make_shadow_copy (fname, &error); - if (!is_ok (&error)) { - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader shadow copy error: %s.", mono_error_get_message (&error)); - mono_error_cleanup (&error); - *status = MONO_IMAGE_IMAGE_INVALID; - g_free (fname); - return NULL; - } - } - if (new_fname && new_fname != fname) { - g_free (fname); - fname = new_fname; - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader shadow-copied assembly to: '%s'.", fname); - } - - image = NULL; - - // If VM built with mkbundle - loaded_from_bundle = FALSE; - if (bundles != NULL) { - image = mono_assembly_open_from_bundle (fname, status, refonly); - loaded_from_bundle = image != NULL; - } - - if (!image) - image = mono_image_open_full (fname, status, refonly); - - if (!image){ - if (*status == MONO_IMAGE_OK) - *status = MONO_IMAGE_ERROR_ERRNO; - g_free (fname); - return NULL; - } - - if (image->assembly) { - /* Already loaded by another appdomain */ - mono_assembly_invoke_load_hook (image->assembly); - mono_image_close (image); - g_free (fname); - return image->assembly; - } - - ass = mono_assembly_load_from_full (image, fname, status, refonly); - - if (ass) { - if (!loaded_from_bundle) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader loaded assembly from location: '%s'.", filename); - if (!refonly) - mono_config_for_assembly (ass->image); - } - - /* Clear the reference added by mono_image_open */ - mono_image_close (image); - - g_free (fname); - - return ass; -} - -static void -free_item (gpointer val, gpointer user_data) -{ - g_free (val); -} - -/** - * mono_assembly_load_friends: - * @ass: an assembly - * - * Load the list of friend assemblies that are allowed to access - * the assembly's internal types and members. They are stored as assembly - * names in custom attributes. - * - * This is an internal method, we need this because when we load mscorlib - * we do not have the internals visible cattr loaded yet, - * so we need to load these after we initialize the runtime. - * - * LOCKING: Acquires the assemblies lock plus the loader lock. - */ -void -mono_assembly_load_friends (MonoAssembly* ass) -{ - MonoError error; - int i; - MonoCustomAttrInfo* attrs; - GSList *list; - - if (ass->friend_assembly_names_inited) - return; - - attrs = mono_custom_attrs_from_assembly_checked (ass, &error); - mono_error_assert_ok (&error); - if (!attrs) { - mono_assemblies_lock (); - ass->friend_assembly_names_inited = TRUE; - mono_assemblies_unlock (); - return; - } - - mono_assemblies_lock (); - if (ass->friend_assembly_names_inited) { - mono_assemblies_unlock (); - return; - } - mono_assemblies_unlock (); - - list = NULL; - /* - * We build the list outside the assemblies lock, the worse that can happen - * is that we'll need to free the allocated list. - */ - for (i = 0; i < attrs->num_attrs; ++i) { - MonoCustomAttrEntry *attr = &attrs->attrs [i]; - MonoAssemblyName *aname; - const gchar *data; - /* Do some sanity checking */ - if (!attr->ctor || attr->ctor->klass != mono_class_try_get_internals_visible_class ()) - continue; - if (attr->data_size < 4) - continue; - data = (const char*)attr->data; - /* 0xFF means null string, see custom attr format */ - if (data [0] != 1 || data [1] != 0 || (data [2] & 0xFF) == 0xFF) - continue; - mono_metadata_decode_value (data + 2, &data); - aname = g_new0 (MonoAssemblyName, 1); - /*g_print ("friend ass: %s\n", data);*/ - if (mono_assembly_name_parse_full (data, aname, TRUE, NULL, NULL)) { - list = g_slist_prepend (list, aname); - } else { - g_free (aname); - } - } - mono_custom_attrs_free (attrs); - - mono_assemblies_lock (); - if (ass->friend_assembly_names_inited) { - mono_assemblies_unlock (); - g_slist_foreach (list, free_item, NULL); - g_slist_free (list); - return; - } - ass->friend_assembly_names = list; - - /* Because of the double checked locking pattern above */ - mono_memory_barrier (); - ass->friend_assembly_names_inited = TRUE; - mono_assemblies_unlock (); -} - -/** - * mono_assembly_open: - * @filename: Opens the assembly pointed out by this name - * @status: return status code - * - * This loads an assembly from the specified @filename. The @filename allows - * a local URL (starting with a file:// prefix). If a file prefix is used, the - * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file - * is treated as a local path. - * - * First, an attempt is made to load the assembly from the bundled executable (for those - * deployments that have been done with the `mkbundle` tool or for scenarios where the - * assembly has been registered as an embedded assembly). If this is not the case, then - * the assembly is loaded from disk using `api:mono_image_open_full`. - * - * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of - * the assembly is made. - * - * Return: a pointer to the MonoAssembly if @filename contains a valid - * assembly or NULL on error. Details about the error are stored in the - * @status variable. - */ -MonoAssembly * -mono_assembly_open (const char *filename, MonoImageOpenStatus *status) -{ - return mono_assembly_open_full (filename, status, FALSE); -} - -/** - * mono_assembly_load_from_full: - * @image: Image to load the assembly from - * @fname: assembly name to associate with the assembly - * @status: returns the status condition - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * If the provided @image has an assembly reference, it will process the given - * image as an assembly with the given name. - * - * Most likely you want to use the `api:mono_assembly_load_full` method instead. - * - * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be - * set to #MONO_IMAGE_OK; or NULL on error. - * - * If there is an error loading the assembly the @status will indicate the - * reason with @status being set to `MONO_IMAGE_INVALID` if the - * image did not contain an assembly reference table. - */ -MonoAssembly * -mono_assembly_load_from_full (MonoImage *image, const char*fname, - MonoImageOpenStatus *status, gboolean refonly) -{ - MonoAssembly *ass, *ass2; - char *base_dir; - - if (!image->tables [MONO_TABLE_ASSEMBLY].rows) { - /* 'image' doesn't have a manifest -- maybe someone is trying to Assembly.Load a .netmodule */ - *status = MONO_IMAGE_IMAGE_INVALID; - return NULL; - } - -#if defined (HOST_WIN32) - { - gchar *tmp_fn; - int i; - - tmp_fn = g_strdup (fname); - for (i = strlen (tmp_fn) - 1; i >= 0; i--) { - if (tmp_fn [i] == '/') - tmp_fn [i] = '\\'; - } - - base_dir = absolute_dir (tmp_fn); - g_free (tmp_fn); - } -#else - base_dir = absolute_dir (fname); -#endif - - /* - * Create assembly struct, and enter it into the assembly cache - */ - ass = g_new0 (MonoAssembly, 1); - ass->basedir = base_dir; - ass->ref_only = refonly; - ass->image = image; - - mono_profiler_assembly_event (ass, MONO_PROFILE_START_LOAD); - - mono_assembly_fill_assembly_name (image, &ass->aname); - - if (mono_defaults.corlib && strcmp (ass->aname.name, "mscorlib") == 0) { - // MS.NET doesn't support loading other mscorlibs - g_free (ass); - g_free (base_dir); - mono_image_addref (mono_defaults.corlib); - *status = MONO_IMAGE_OK; - return mono_defaults.corlib->assembly; - } - - /* Add a non-temporary reference because of ass->image */ - mono_image_addref (image); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image addref %s[%p] -> %s[%p]: %d", ass->aname.name, ass, image->name, image, image->ref_count); - - /* - * The load hooks might take locks so we can't call them while holding the - * assemblies lock. - */ - if (ass->aname.name) { - ass2 = mono_assembly_invoke_search_hook_internal (&ass->aname, NULL, refonly, FALSE); - if (ass2) { - g_free (ass); - g_free (base_dir); - mono_image_close (image); - *status = MONO_IMAGE_OK; - return ass2; - } - } - - mono_assemblies_lock (); - - if (image->assembly) { - /* - * This means another thread has already loaded the assembly, but not yet - * called the load hooks so the search hook can't find the assembly. - */ - mono_assemblies_unlock (); - ass2 = image->assembly; - g_free (ass); - g_free (base_dir); - mono_image_close (image); - *status = MONO_IMAGE_OK; - return ass2; - } - - image->assembly = ass; - - loaded_assemblies = g_list_prepend (loaded_assemblies, ass); - mono_assemblies_unlock (); - -#ifdef HOST_WIN32 - if (image->is_module_handle) - mono_image_fixup_vtable (image); -#endif - - mono_assembly_invoke_load_hook (ass); - - mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK); - - return ass; -} - -/** - * mono_assembly_load_from: - * @image: Image to load the assembly from - * @fname: assembly name to associate with the assembly - * @status: return status code - * - * If the provided @image has an assembly reference, it will process the given - * image as an assembly with the given name. - * - * Most likely you want to use the `api:mono_assembly_load_full` method instead. - * - * This is equivalent to calling `api:mono_assembly_load_from_full` with the - * @refonly parameter set to FALSE. - * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be - * set to #MONO_IMAGE_OK; or NULL on error. - * - * If there is an error loading the assembly the @status will indicate the - * reason with @status being set to `MONO_IMAGE_INVALID` if the - * image did not contain an assembly reference table. - - */ -MonoAssembly * -mono_assembly_load_from (MonoImage *image, const char *fname, - MonoImageOpenStatus *status) -{ - return mono_assembly_load_from_full (image, fname, status, FALSE); -} - -/** - * mono_assembly_name_free: - * @aname: assembly name to free - * - * Frees the provided assembly name object. - * (it does not frees the object itself, only the name members). - */ -void -mono_assembly_name_free (MonoAssemblyName *aname) -{ - if (aname == NULL) - return; - - g_free ((void *) aname->name); - g_free ((void *) aname->culture); - g_free ((void *) aname->hash_value); -} - -static gboolean -parse_public_key (const gchar *key, gchar** pubkey, gboolean *is_ecma) -{ - const gchar *pkey; - gchar header [16], val, *arr; - gint i, j, offset, bitlen, keylen, pkeylen; - - keylen = strlen (key) >> 1; - if (keylen < 1) - return FALSE; - - /* allow the ECMA standard key */ - if (strcmp (key, "00000000000000000400000000000000") == 0) { - if (pubkey) { - *pubkey = g_strdup (key); - *is_ecma = TRUE; - } - return TRUE; - } - *is_ecma = FALSE; - val = g_ascii_xdigit_value (key [0]) << 4; - val |= g_ascii_xdigit_value (key [1]); - switch (val) { - case 0x00: - if (keylen < 13) - return FALSE; - val = g_ascii_xdigit_value (key [24]); - val |= g_ascii_xdigit_value (key [25]); - if (val != 0x06) - return FALSE; - pkey = key + 24; - break; - case 0x06: - pkey = key; - break; - default: - return FALSE; - } - - /* We need the first 16 bytes - * to check whether this key is valid or not */ - pkeylen = strlen (pkey) >> 1; - if (pkeylen < 16) - return FALSE; - - for (i = 0, j = 0; i < 16; i++) { - header [i] = g_ascii_xdigit_value (pkey [j++]) << 4; - header [i] |= g_ascii_xdigit_value (pkey [j++]); - } - - if (header [0] != 0x06 || /* PUBLICKEYBLOB (0x06) */ - header [1] != 0x02 || /* Version (0x02) */ - header [2] != 0x00 || /* Reserved (word) */ - header [3] != 0x00 || - (guint)(read32 (header + 8)) != 0x31415352) /* DWORD magic = RSA1 */ - return FALSE; - - /* Based on this length, we _should_ be able to know if the length is right */ - bitlen = read32 (header + 12) >> 3; - if ((bitlen + 16 + 4) != pkeylen) - return FALSE; - - /* parsing is OK and the public key itself is not requested back */ - if (!pubkey) - return TRUE; - - /* Encode the size of the blob */ - offset = 0; - if (keylen <= 127) { - arr = (gchar *)g_malloc (keylen + 1); - arr [offset++] = keylen; - } else { - arr = (gchar *)g_malloc (keylen + 2); - arr [offset++] = 0x80; /* 10bs */ - arr [offset++] = keylen; - } - - for (i = offset, j = 0; i < keylen + offset; i++) { - arr [i] = g_ascii_xdigit_value (key [j++]) << 4; - arr [i] |= g_ascii_xdigit_value (key [j++]); - } - - *pubkey = arr; - - return TRUE; -} - -static gboolean -build_assembly_name (const char *name, const char *version, const char *culture, const char *token, const char *key, guint32 flags, guint32 arch, MonoAssemblyName *aname, gboolean save_public_key) -{ - gint major, minor, build, revision; - gint len; - gint version_parts; - gchar *pkey, *pkeyptr, *encoded, tok [8]; - - memset (aname, 0, sizeof (MonoAssemblyName)); - - if (version) { - version_parts = sscanf (version, "%u.%u.%u.%u", &major, &minor, &build, &revision); - if (version_parts < 2 || version_parts > 4) - return FALSE; - - /* FIXME: we should set build & revision to -1 (instead of 0) - if these are not set in the version string. That way, later on, - we can still determine if these were specified. */ - aname->major = major; - aname->minor = minor; - if (version_parts >= 3) - aname->build = build; - else - aname->build = 0; - if (version_parts == 4) - aname->revision = revision; - else - aname->revision = 0; - } - - aname->flags = flags; - aname->arch = arch; - aname->name = g_strdup (name); - - if (culture) { - if (g_ascii_strcasecmp (culture, "neutral") == 0) - aname->culture = g_strdup (""); - else - aname->culture = g_strdup (culture); - } - - if (token && strncmp (token, "null", 4) != 0) { - char *lower; - - /* the constant includes the ending NULL, hence the -1 */ - if (strlen (token) != (MONO_PUBLIC_KEY_TOKEN_LENGTH - 1)) { - mono_assembly_name_free (aname); - return FALSE; - } - lower = g_ascii_strdown (token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_strlcpy ((char*)aname->public_key_token, lower, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (lower); - } - - if (key) { - gboolean is_ecma; - if (strcmp (key, "null") == 0 || !parse_public_key (key, &pkey, &is_ecma)) { - mono_assembly_name_free (aname); - return FALSE; - } - - if (is_ecma) { - if (save_public_key) - aname->public_key = (guint8*)pkey; - else - g_free (pkey); - g_strlcpy ((gchar*)aname->public_key_token, "b77a5c561934e089", MONO_PUBLIC_KEY_TOKEN_LENGTH); - return TRUE; - } - - len = mono_metadata_decode_blob_size ((const gchar *) pkey, (const gchar **) &pkeyptr); - // We also need to generate the key token - mono_digest_get_public_token ((guchar*) tok, (guint8*) pkeyptr, len); - encoded = encode_public_tok ((guchar*) tok, 8); - g_strlcpy ((gchar*)aname->public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (encoded); - - if (save_public_key) - aname->public_key = (guint8*) pkey; - else - g_free (pkey); - } - - return TRUE; -} - -static gboolean -parse_assembly_directory_name (const char *name, const char *dirname, MonoAssemblyName *aname) -{ - gchar **parts; - gboolean res; - - parts = g_strsplit (dirname, "_", 3); - if (!parts || !parts[0] || !parts[1] || !parts[2]) { - g_strfreev (parts); - return FALSE; - } - - res = build_assembly_name (name, parts[0], parts[1], parts[2], NULL, 0, 0, aname, FALSE); - g_strfreev (parts); - return res; -} - -static gboolean -split_key_value (const gchar *pair, gchar **key, guint32 *keylen, gchar **value) -{ - char *eqsign = strchr (pair, '='); - if (!eqsign) { - *key = NULL; - *keylen = 0; - *value = NULL; - return FALSE; - } - - *key = (gchar*)pair; - *keylen = eqsign - *key; - while (*keylen > 0 && g_ascii_isspace ((*key) [*keylen - 1])) - (*keylen)--; - *value = g_strstrip (eqsign + 1); - return TRUE; -} - -gboolean -mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboolean save_public_key, gboolean *is_version_defined, gboolean *is_token_defined) -{ - gchar *dllname; - gchar *dllname_uq; - gchar *version = NULL; - gchar *version_uq; - gchar *culture = NULL; - gchar *culture_uq; - gchar *token = NULL; - gchar *token_uq; - gchar *key = NULL; - gchar *key_uq; - gchar *retargetable = NULL; - gchar *retargetable_uq; - gchar *procarch; - gchar *procarch_uq; - gboolean res; - gchar *value, *part_name; - guint32 part_name_len; - gchar **parts; - gchar **tmp; - gboolean version_defined; - gboolean token_defined; - guint32 flags = 0; - guint32 arch = MONO_PROCESSOR_ARCHITECTURE_NONE; - - if (!is_version_defined) - is_version_defined = &version_defined; - *is_version_defined = FALSE; - if (!is_token_defined) - is_token_defined = &token_defined; - *is_token_defined = FALSE; - - parts = tmp = g_strsplit (name, ",", 6); - if (!tmp || !*tmp) { - g_strfreev (tmp); - return FALSE; - } - - dllname = g_strstrip (*tmp); - - tmp++; - - while (*tmp) { - if (!split_key_value (g_strstrip (*tmp), &part_name, &part_name_len, &value)) - goto cleanup_and_fail; - - if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Version", part_name_len)) { - *is_version_defined = TRUE; - version = value; - if (strlen (version) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Culture", part_name_len)) { - culture = value; - if (strlen (culture) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 14 && !g_ascii_strncasecmp (part_name, "PublicKeyToken", part_name_len)) { - *is_token_defined = TRUE; - token = value; - if (strlen (token) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 9 && !g_ascii_strncasecmp (part_name, "PublicKey", part_name_len)) { - key = value; - if (strlen (key) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 12 && !g_ascii_strncasecmp (part_name, "Retargetable", part_name_len)) { - retargetable = value; - retargetable_uq = unquote (retargetable); - if (retargetable_uq != NULL) - retargetable = retargetable_uq; - - if (!g_ascii_strcasecmp (retargetable, "yes")) { - flags |= ASSEMBLYREF_RETARGETABLE_FLAG; - } else if (g_ascii_strcasecmp (retargetable, "no")) { - free (retargetable_uq); - goto cleanup_and_fail; - } - - free (retargetable_uq); - tmp++; - continue; - } - - if (part_name_len == 21 && !g_ascii_strncasecmp (part_name, "ProcessorArchitecture", part_name_len)) { - procarch = value; - procarch_uq = unquote (procarch); - if (procarch_uq != NULL) - procarch = procarch_uq; - - if (!g_ascii_strcasecmp (procarch, "MSIL")) - arch = MONO_PROCESSOR_ARCHITECTURE_MSIL; - else if (!g_ascii_strcasecmp (procarch, "X86")) - arch = MONO_PROCESSOR_ARCHITECTURE_X86; - else if (!g_ascii_strcasecmp (procarch, "IA64")) - arch = MONO_PROCESSOR_ARCHITECTURE_IA64; - else if (!g_ascii_strcasecmp (procarch, "AMD64")) - arch = MONO_PROCESSOR_ARCHITECTURE_AMD64; - else { - free (procarch_uq); - goto cleanup_and_fail; - } - - free (procarch_uq); - tmp++; - continue; - } - - g_strfreev (parts); - return FALSE; - } - - /* if retargetable flag is set, then we must have a fully qualified name */ - if (retargetable != NULL && (version == NULL || culture == NULL || (key == NULL && token == NULL))) { - goto cleanup_and_fail; - } - - dllname_uq = unquote (dllname); - version_uq = unquote (version); - culture_uq = unquote (culture); - token_uq = unquote (token); - key_uq = unquote (key); - - res = build_assembly_name ( - dllname_uq == NULL ? dllname : dllname_uq, - version_uq == NULL ? version : version_uq, - culture_uq == NULL ? culture : culture_uq, - token_uq == NULL ? token : token_uq, - key_uq == NULL ? key : key_uq, - flags, arch, aname, save_public_key); - - free (dllname_uq); - free (version_uq); - free (culture_uq); - free (token_uq); - free (key_uq); - - g_strfreev (parts); - return res; - -cleanup_and_fail: - g_strfreev (parts); - return FALSE; -} - -static char* -unquote (const char *str) -{ - gint slen; - const char *end; - - if (str == NULL) - return NULL; - - slen = strlen (str); - if (slen < 2) - return NULL; - - if (*str != '\'' && *str != '\"') - return NULL; - - end = str + slen - 1; - if (*str != *end) - return NULL; - - return g_strndup (str + 1, slen - 2); -} - -/** - * mono_assembly_name_parse: - * @name: name to parse - * @aname: the destination assembly name - * - * Parses an assembly qualified type name and assigns the name, - * version, culture and token to the provided assembly name object. - * - * Returns: TRUE if the name could be parsed. - */ -gboolean -mono_assembly_name_parse (const char *name, MonoAssemblyName *aname) -{ - return mono_assembly_name_parse_full (name, aname, FALSE, NULL, NULL); -} - -/** - * mono_assembly_name_new: - * @name: name to parse - * - * Allocate a new MonoAssemblyName and fill its values from the - * passed @name. - * - * Returns: a newly allocated structure or NULL if there was any failure. - */ -MonoAssemblyName* -mono_assembly_name_new (const char *name) -{ - MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1); - if (mono_assembly_name_parse (name, aname)) - return aname; - g_free (aname); - return NULL; -} - -const char* -mono_assembly_name_get_name (MonoAssemblyName *aname) -{ - return aname->name; -} - -const char* -mono_assembly_name_get_culture (MonoAssemblyName *aname) -{ - return aname->culture; -} - -mono_byte* -mono_assembly_name_get_pubkeytoken (MonoAssemblyName *aname) -{ - if (aname->public_key_token [0]) - return aname->public_key_token; - return NULL; -} - -uint16_t -mono_assembly_name_get_version (MonoAssemblyName *aname, uint16_t *minor, uint16_t *build, uint16_t *revision) -{ - if (minor) - *minor = aname->minor; - if (build) - *build = aname->build; - if (revision) - *revision = aname->revision; - return aname->major; -} - -static MonoAssembly* -probe_for_partial_name (const char *basepath, const char *fullname, MonoAssemblyName *aname, MonoImageOpenStatus *status) -{ - gchar *fullpath = NULL; - GDir *dirhandle; - const char* direntry; - MonoAssemblyName gac_aname; - gint major=-1, minor=0, build=0, revision=0; - gboolean exact_version; - - dirhandle = g_dir_open (basepath, 0, NULL); - if (!dirhandle) - return NULL; - - exact_version = (aname->major | aname->minor | aname->build | aname->revision) != 0; - - while ((direntry = g_dir_read_name (dirhandle))) { - gboolean match = TRUE; - - if(!parse_assembly_directory_name (aname->name, direntry, &gac_aname)) - continue; - - if (aname->culture != NULL && strcmp (aname->culture, gac_aname.culture) != 0) - match = FALSE; - - if (match && strlen ((char*)aname->public_key_token) > 0 && - !mono_public_tokens_are_equal (aname->public_key_token, gac_aname.public_key_token)) - match = FALSE; - - if (match) { - if (exact_version) { - match = (aname->major == gac_aname.major && aname->minor == gac_aname.minor && - aname->build == gac_aname.build && aname->revision == gac_aname.revision); - } - else if (gac_aname.major < major) - match = FALSE; - else if (gac_aname.major == major) { - if (gac_aname.minor < minor) - match = FALSE; - else if (gac_aname.minor == minor) { - if (gac_aname.build < build) - match = FALSE; - else if (gac_aname.build == build && gac_aname.revision <= revision) - match = FALSE; - } - } - } - - if (match) { - major = gac_aname.major; - minor = gac_aname.minor; - build = gac_aname.build; - revision = gac_aname.revision; - g_free (fullpath); - fullpath = g_build_path (G_DIR_SEPARATOR_S, basepath, direntry, fullname, NULL); - } - - mono_assembly_name_free (&gac_aname); - } - - g_dir_close (dirhandle); - - if (fullpath == NULL) - return NULL; - else { - MonoAssembly *res = mono_assembly_open (fullpath, status); - g_free (fullpath); - return res; - } -} - -/** - * mono_assembly_load_with_partial_name: - * @name: an assembly name that is then parsed by `api:mono_assembly_name_parse`. - * @status: return status code - * - * Loads a Mono Assembly from a name. The name is parsed using `api:mono_assembly_name_parse`, - * so it might contain a qualified type name, version, culture and token. - * - * This will load the assembly from the file whose name is derived from the assembly name - * by appending the .dll extension. - * - * The assembly is loaded from either one of the extra Global Assembly Caches specified - * by the extra GAC paths (specified by the `MONO_GAC_PREFIX` environment variable) or - * if that fails from the GAC. - * - * Returns: NULL on failure, or a pointer to a MonoAssembly on success. - */ -MonoAssembly* -mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status) -{ - MonoError error; - MonoAssembly *res; - MonoAssemblyName *aname, base_name; - MonoAssemblyName mapped_aname; - gchar *fullname, *gacpath; - gchar **paths; - - memset (&base_name, 0, sizeof (MonoAssemblyName)); - aname = &base_name; - - if (!mono_assembly_name_parse (name, aname)) - return NULL; - - /* - * If no specific version has been requested, make sure we load the - * correct version for system assemblies. - */ - if ((aname->major | aname->minor | aname->build | aname->revision) == 0) - aname = mono_assembly_remap_version (aname, &mapped_aname); - - res = mono_assembly_loaded (aname); - if (res) { - mono_assembly_name_free (aname); - return res; - } - - res = invoke_assembly_preload_hook (aname, assemblies_path); - if (res) { - res->in_gac = FALSE; - mono_assembly_name_free (aname); - return res; - } - - fullname = g_strdup_printf ("%s.dll", aname->name); - - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!res && *paths) { - gacpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", aname->name, NULL); - res = probe_for_partial_name (gacpath, fullname, aname, status); - g_free (gacpath); - paths++; - } - } - - if (res) { - res->in_gac = TRUE; - g_free (fullname); - mono_assembly_name_free (aname); - return res; - } - - gacpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), "mono", "gac", aname->name, NULL); - res = probe_for_partial_name (gacpath, fullname, aname, status); - g_free (gacpath); - - if (res) - res->in_gac = TRUE; - else { - MonoDomain *domain = mono_domain_get (); - MonoReflectionAssembly *refasm; - - refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE, &error); - if (!is_ok (&error)) { - g_free (fullname); - mono_assembly_name_free (aname); - mono_error_cleanup (&error); - if (*status == MONO_IMAGE_OK) - *status = MONO_IMAGE_IMAGE_INVALID; - } - - if (refasm) - res = refasm->assembly; - } - - g_free (fullname); - mono_assembly_name_free (aname); - - return res; -} - -static MonoBoolean -mono_assembly_is_in_gac (const gchar *filename) -{ - const gchar *rootdir; - gchar *gp; - gchar **paths; - - if (filename == NULL) - return FALSE; - - for (paths = extra_gac_paths; paths && *paths; paths++) { - if (strstr (*paths, filename) != *paths) - continue; - - gp = (gchar *) (filename + strlen (*paths)); - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "lib", 3)) - continue; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "mono", 4)) - continue; - gp += 4; - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "gac", 3)) - continue; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - continue; - - return TRUE; - } - - rootdir = mono_assembly_getrootdir (); - if (strstr (filename, rootdir) != filename) - return FALSE; - - gp = (gchar *) (filename + strlen (rootdir)); - if (*gp != G_DIR_SEPARATOR) - return FALSE; - gp++; - if (strncmp (gp, "mono", 4)) - return FALSE; - gp += 4; - if (*gp != G_DIR_SEPARATOR) - return FALSE; - gp++; - if (strncmp (gp, "gac", 3)) - return FALSE; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - return FALSE; - return TRUE; -} - -static MonoImage* -mono_assembly_load_publisher_policy (MonoAssemblyName *aname) -{ - MonoImage *image; - gchar *filename, *pname, *name, *culture, *version, *fullpath, *subpath; - gchar **paths; - gint32 len; - - if (strstr (aname->name, ".dll")) { - len = strlen (aname->name) - 4; - name = (gchar *)g_malloc (len + 1); - strncpy (name, aname->name, len); - name[len] = 0; - } else - name = g_strdup (aname->name); - - if (aname->culture) - culture = g_utf8_strdown (aname->culture, -1); - else - culture = g_strdup (""); - - pname = g_strdup_printf ("policy.%d.%d.%s", aname->major, aname->minor, name); - version = g_strdup_printf ("0.0.0.0_%s_%s", culture, aname->public_key_token); - g_free (name); - g_free (culture); - - filename = g_strconcat (pname, ".dll", NULL); - subpath = g_build_path (G_DIR_SEPARATOR_S, pname, version, filename, NULL); - g_free (pname); - g_free (version); - g_free (filename); - - image = NULL; - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!image && *paths) { - fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, - "lib", "mono", "gac", subpath, NULL); - image = mono_image_open (fullpath, NULL); - g_free (fullpath); - paths++; - } - } - - if (image) { - g_free (subpath); - return image; - } - - fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), - "mono", "gac", subpath, NULL); - image = mono_image_open (fullpath, NULL); - g_free (subpath); - g_free (fullpath); - - return image; -} - -static MonoAssemblyName* -mono_assembly_bind_version (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname, MonoAssemblyName *dest_name) -{ - memcpy (dest_name, aname, sizeof (MonoAssemblyName)); - dest_name->major = info->new_version.major; - dest_name->minor = info->new_version.minor; - dest_name->build = info->new_version.build; - dest_name->revision = info->new_version.revision; - - return dest_name; -} - -/* LOCKING: assembly_binding lock must be held */ -static MonoAssemblyBindingInfo* -search_binding_loaded (MonoAssemblyName *aname) -{ - GSList *tmp; - - for (tmp = loaded_assembly_bindings; tmp; tmp = tmp->next) { - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)tmp->data; - if (assembly_binding_maps_name (info, aname)) - return info; - } - - return NULL; -} - -static inline gboolean -info_compare_versions (AssemblyVersionSet *left, AssemblyVersionSet *right) -{ - if (left->major != right->major || left->minor != right->minor || - left->build != right->build || left->revision != right->revision) - return FALSE; - - return TRUE; -} - -static inline gboolean -info_versions_equal (MonoAssemblyBindingInfo *left, MonoAssemblyBindingInfo *right) -{ - if (left->has_old_version_bottom != right->has_old_version_bottom) - return FALSE; - - if (left->has_old_version_top != right->has_old_version_top) - return FALSE; - - if (left->has_new_version != right->has_new_version) - return FALSE; - - if (left->has_old_version_bottom && !info_compare_versions (&left->old_version_bottom, &right->old_version_bottom)) - return FALSE; - - if (left->has_old_version_top && !info_compare_versions (&left->old_version_top, &right->old_version_top)) - return FALSE; - - if (left->has_new_version && !info_compare_versions (&left->new_version, &right->new_version)) - return FALSE; - - return TRUE; -} - -/* LOCKING: assumes all the necessary locks are held */ -static void -assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data) -{ - MonoAssemblyBindingInfo *info_copy; - GSList *tmp; - MonoAssemblyBindingInfo *info_tmp; - MonoDomain *domain = (MonoDomain*)user_data; - - if (!domain) - return; - - for (tmp = domain->assembly_bindings; tmp; tmp = tmp->next) { - info_tmp = (MonoAssemblyBindingInfo *)tmp->data; - if (strcmp (info->name, info_tmp->name) == 0 && info_versions_equal (info, info_tmp)) - return; - } - - info_copy = (MonoAssemblyBindingInfo *)mono_mempool_alloc0 (domain->mp, sizeof (MonoAssemblyBindingInfo)); - memcpy (info_copy, info, sizeof (MonoAssemblyBindingInfo)); - if (info->name) - info_copy->name = mono_mempool_strdup (domain->mp, info->name); - if (info->culture) - info_copy->culture = mono_mempool_strdup (domain->mp, info->culture); - - domain->assembly_bindings = g_slist_append_mempool (domain->mp, domain->assembly_bindings, info_copy); -} - -static int -get_version_number (int major, int minor) -{ - return major * 256 + minor; -} - -static inline gboolean -info_major_minor_in_range (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) -{ - int aname_version_number = get_version_number (aname->major, aname->minor); - if (!info->has_old_version_bottom) - return FALSE; - - if (get_version_number (info->old_version_bottom.major, info->old_version_bottom.minor) > aname_version_number) - return FALSE; - - if (info->has_old_version_top && get_version_number (info->old_version_top.major, info->old_version_top.minor) < aname_version_number) - return FALSE; - - /* This is not the nicest way to do it, but it's a by-product of the way parsing is done */ - info->major = aname->major; - info->minor = aname->minor; - - return TRUE; -} - -/* LOCKING: Assumes that we are already locked - both loader and domain locks */ -static MonoAssemblyBindingInfo* -get_per_domain_assembly_binding_info (MonoDomain *domain, MonoAssemblyName *aname) -{ - MonoAssemblyBindingInfo *info; - GSList *list; - - if (!domain->assembly_bindings) - return NULL; - - info = NULL; - for (list = domain->assembly_bindings; list; list = list->next) { - info = (MonoAssemblyBindingInfo *)list->data; - if (info && !strcmp (aname->name, info->name) && info_major_minor_in_range (info, aname)) - break; - info = NULL; - } - - if (info) { - if (info->name && info->public_key_token [0] && info->has_old_version_bottom && - info->has_new_version && assembly_binding_maps_name (info, aname)) - info->is_valid = TRUE; - else - info->is_valid = FALSE; - } - - return info; -} - -static MonoAssemblyName* -mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_name) -{ - MonoError error; - MonoAssemblyBindingInfo *info, *info2; - MonoImage *ppimage; - MonoDomain *domain; - - if (aname->public_key_token [0] == 0) - return aname; - - domain = mono_domain_get (); - - mono_assembly_binding_lock (); - info = search_binding_loaded (aname); - mono_assembly_binding_unlock (); - - if (!info) { - mono_domain_lock (domain); - info = get_per_domain_assembly_binding_info (domain, aname); - mono_domain_unlock (domain); - } - - if (info) { - if (!check_policy_versions (info, aname)) - return aname; - - mono_assembly_bind_version (info, aname, dest_name); - return dest_name; - } - - if (domain && domain->setup && domain->setup->configuration_file) { - mono_domain_lock (domain); - if (!domain->assembly_bindings_parsed) { - gchar *domain_config_file_name = mono_string_to_utf8_checked (domain->setup->configuration_file, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - - gchar *domain_config_file_path = mono_portability_find_file (domain_config_file_name, TRUE); - - if (!domain_config_file_path) - domain_config_file_path = domain_config_file_name; - - mono_config_parse_assembly_bindings (domain_config_file_path, aname->major, aname->minor, domain, assembly_binding_info_parsed); - domain->assembly_bindings_parsed = TRUE; - if (domain_config_file_name != domain_config_file_path) - g_free (domain_config_file_name); - g_free (domain_config_file_path); - } - - info2 = get_per_domain_assembly_binding_info (domain, aname); - - if (info2) { - info = (MonoAssemblyBindingInfo *)g_memdup (info2, sizeof (MonoAssemblyBindingInfo)); - info->name = g_strdup (info2->name); - info->culture = g_strdup (info2->culture); - info->domain_id = domain->domain_id; - } - - mono_domain_unlock (domain); - } - - if (!info) { - info = g_new0 (MonoAssemblyBindingInfo, 1); - info->major = aname->major; - info->minor = aname->minor; - } - - if (!info->is_valid) { - ppimage = mono_assembly_load_publisher_policy (aname); - if (ppimage) { - get_publisher_policy_info (ppimage, aname, info); - mono_image_close (ppimage); - } - } - - /* Define default error value if needed */ - if (!info->is_valid) { - info->name = g_strdup (aname->name); - info->culture = g_strdup (aname->culture); - g_strlcpy ((char *)info->public_key_token, (const char *)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } - - mono_assembly_binding_lock (); - info2 = search_binding_loaded (aname); - if (info2) { - /* This binding was added by another thread - * before us */ - mono_assembly_binding_info_free (info); - g_free (info); - - info = info2; - } else - loaded_assembly_bindings = g_slist_prepend (loaded_assembly_bindings, info); - - mono_assembly_binding_unlock (); - - if (!info->is_valid || !check_policy_versions (info, aname)) - return aname; - - mono_assembly_bind_version (info, aname, dest_name); - return dest_name; -} - -/** - * mono_assembly_load_from_gac - * - * @aname: The assembly name object - */ -static MonoAssembly* -mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImageOpenStatus *status, MonoBoolean refonly) -{ - MonoAssembly *result = NULL; - gchar *name, *version, *culture, *fullpath, *subpath; - gint32 len; - gchar **paths; - char *pubtok; - - if (aname->public_key_token [0] == 0) { - return NULL; - } - - if (strstr (aname->name, ".dll")) { - len = strlen (filename) - 4; - name = (gchar *)g_malloc (len + 1); - strncpy (name, aname->name, len); - name[len] = 0; - } else { - name = g_strdup (aname->name); - } - - if (aname->culture) { - culture = g_utf8_strdown (aname->culture, -1); - } else { - culture = g_strdup (""); - } - - pubtok = g_ascii_strdown ((char*)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - version = g_strdup_printf ("%d.%d.%d.%d_%s_%s", aname->major, - aname->minor, aname->build, aname->revision, - culture, pubtok); - g_free (pubtok); - - subpath = g_build_path (G_DIR_SEPARATOR_S, name, version, filename, NULL); - g_free (name); - g_free (version); - g_free (culture); - - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!result && *paths) { - fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", subpath, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - paths++; - } - } - - if (result) { - result->in_gac = TRUE; - g_free (subpath); - return result; - } - - fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), - "mono", "gac", subpath, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - - if (result) - result->in_gac = TRUE; - - g_free (subpath); - - return result; -} - -MonoAssembly* -mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *status) -{ - char *corlib_file; - MonoAssemblyName *aname; - - if (corlib) { - /* g_print ("corlib already loaded\n"); */ - 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); - mono_assembly_name_free (aname); - g_free (aname); - if (corlib != NULL) - goto return_corlib_and_facades; - - // This unusual directory layout can occur if mono is being built and run out of its own source repo - if (assemblies_path) { // Custom assemblies path set via MONO_PATH or mono_set_assemblies_path - corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE); - if (corlib) - goto return_corlib_and_facades; - } - - /* Normal case: Load corlib from mono/ */ - corlib_file = g_build_filename ("mono", runtime->framework_version, "mscorlib.dll", NULL); - if (assemblies_path) { // Custom assemblies path - corlib = load_in_path (corlib_file, (const char**)assemblies_path, status, FALSE); - if (corlib) { - g_free (corlib_file); - goto return_corlib_and_facades; - } - } - corlib = load_in_path (corlib_file, default_path, status, FALSE); - g_free (corlib_file); - -return_corlib_and_facades: - if (corlib && !strcmp (runtime->framework_version, "4.5")) // FIXME: stop hardcoding 4.5 here - default_path [1] = g_strdup_printf ("%s/Facades", corlib->basedir); - - return corlib; -} - -MonoAssembly* -mono_assembly_load_full_nosearch (MonoAssemblyName *aname, - const char *basedir, - MonoImageOpenStatus *status, - gboolean refonly) -{ - MonoAssembly *result; - char *fullpath, *filename; - MonoAssemblyName maped_aname; - MonoAssemblyName maped_name_pp; - int ext_index; - const char *ext; - int len; - - aname = mono_assembly_remap_version (aname, &maped_aname); - - /* Reflection only assemblies don't get assembly binding */ - if (!refonly) - aname = mono_assembly_apply_binding (aname, &maped_name_pp); - - result = mono_assembly_loaded_full (aname, refonly); - if (result) - return result; - - result = refonly ? invoke_assembly_refonly_preload_hook (aname, assemblies_path) : invoke_assembly_preload_hook (aname, assemblies_path); - if (result) { - result->in_gac = FALSE; - return result; - } - - /* Currently we retrieve the loaded corlib for reflection - * only requests, like a common reflection only assembly - */ - if (strcmp (aname->name, "mscorlib") == 0 || strcmp (aname->name, "mscorlib.dll") == 0) { - return mono_assembly_load_corlib (mono_get_runtime_info (), status); - } - - len = strlen (aname->name); - for (ext_index = 0; ext_index < 2; ext_index ++) { - ext = ext_index == 0 ? ".dll" : ".exe"; - if (len > 4 && (!strcmp (aname->name + len - 4, ".dll") || !strcmp (aname->name + len - 4, ".exe"))) { - filename = g_strdup (aname->name); - /* Don't try appending .dll/.exe if it already has one of those extensions */ - ext_index++; - } else { - filename = g_strconcat (aname->name, ext, NULL); - } - - result = mono_assembly_load_from_gac (aname, filename, status, refonly); - if (result) { - g_free (filename); - return result; - } - - if (basedir) { - fullpath = g_build_filename (basedir, filename, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - if (result) { - result->in_gac = FALSE; - g_free (filename); - return result; - } - } - - result = load_in_path (filename, default_path, status, refonly); - if (result) - result->in_gac = FALSE; - g_free (filename); - if (result) - return result; - } - - return result; -} - -MonoAssembly* -mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly) -{ - MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly); - - if (!result) - /* Try a postload search hook */ - result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE); - return result; -} - -/** - * mono_assembly_load_full: - * @aname: A MonoAssemblyName with the assembly name to load. - * @basedir: A directory to look up the assembly at. - * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it - * attempts to load the assembly from that directory before probing the standard locations. - * - * If the assembly is being opened in reflection-only mode (@refonly set to TRUE) then no - * assembly binding takes place. - * - * Returns: the assembly referenced by @aname loaded or NULL on error. On error the - * value pointed by status is updated with an error code. - */ -MonoAssembly* -mono_assembly_load_full (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status, gboolean refonly) -{ - return mono_assembly_load_full_internal (aname, NULL, basedir, status, refonly); -} - -/** - * mono_assembly_load: - * @aname: A MonoAssemblyName with the assembly name to load. - * @basedir: A directory to look up the assembly at. - * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation - * - * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it - * attempts to load the assembly from that directory before probing the standard locations. - * - * Returns: the assembly referenced by @aname loaded or NULL on error. On error the - * value pointed by status is updated with an error code. - */ -MonoAssembly* -mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status) -{ - return mono_assembly_load_full_internal (aname, NULL, basedir, status, FALSE); -} - -/** - * mono_assembly_loaded_full: - * @aname: an assembly to look for. - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * This is used to determine if the specified assembly has been loaded - * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to - * a `MonoAssembly` that matches the `MonoAssemblyName` specified. - */ -MonoAssembly* -mono_assembly_loaded_full (MonoAssemblyName *aname, gboolean refonly) -{ - MonoAssembly *res; - MonoAssemblyName maped_aname; - - aname = mono_assembly_remap_version (aname, &maped_aname); - - res = mono_assembly_invoke_search_hook_internal (aname, NULL, refonly, FALSE); - - return res; -} - -/** - * mono_assembly_loaded: - * @aname: an assembly to look for. - * - * This is used to determine if the specified assembly has been loaded - - * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to - * a `MonoAssembly` that matches the `MonoAssemblyName` specified. - */ -MonoAssembly* -mono_assembly_loaded (MonoAssemblyName *aname) -{ - return mono_assembly_loaded_full (aname, FALSE); -} - -void -mono_assembly_release_gc_roots (MonoAssembly *assembly) -{ - if (assembly == NULL || assembly == REFERENCE_MISSING) - return; - - if (assembly_is_dynamic (assembly)) { - int i; - MonoDynamicImage *dynimg = (MonoDynamicImage *)assembly->image; - for (i = 0; i < dynimg->image.module_count; ++i) - mono_dynamic_image_release_gc_roots ((MonoDynamicImage *)dynimg->image.modules [i]); - mono_dynamic_image_release_gc_roots (dynimg); - } -} - -/* - * Returns whether mono_assembly_close_finish() must be called as - * well. See comment for mono_image_close_except_pools() for why we - * unload in two steps. - */ -gboolean -mono_assembly_close_except_image_pools (MonoAssembly *assembly) -{ - GSList *tmp; - g_return_val_if_fail (assembly != NULL, FALSE); - - if (assembly == REFERENCE_MISSING) - return FALSE; - - /* Might be 0 already */ - if (InterlockedDecrement (&assembly->ref_count) > 0) - return FALSE; - - mono_profiler_assembly_event (assembly, MONO_PROFILE_START_UNLOAD); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading assembly %s [%p].", assembly->aname.name, assembly); - - mono_debug_close_image (assembly->image); - - mono_assemblies_lock (); - loaded_assemblies = g_list_remove (loaded_assemblies, assembly); - mono_assemblies_unlock (); - - assembly->image->assembly = NULL; - - if (!mono_image_close_except_pools (assembly->image)) - assembly->image = NULL; - - for (tmp = assembly->friend_assembly_names; tmp; tmp = tmp->next) { - MonoAssemblyName *fname = (MonoAssemblyName *)tmp->data; - mono_assembly_name_free (fname); - g_free (fname); - } - g_slist_free (assembly->friend_assembly_names); - g_free (assembly->basedir); - - mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD); - - return TRUE; -} - -void -mono_assembly_close_finish (MonoAssembly *assembly) -{ - g_assert (assembly && assembly != REFERENCE_MISSING); - - if (assembly->image) - mono_image_close_finish (assembly->image); - - if (assembly_is_dynamic (assembly)) { - g_free ((char*)assembly->aname.culture); - } else { - g_free (assembly); - } -} - -/** - * mono_assembly_close: - * @assembly: the assembly to release. - * - * This method releases a reference to the @assembly. The assembly is - * only released when all the outstanding references to it are released. - */ -void -mono_assembly_close (MonoAssembly *assembly) -{ - if (mono_assembly_close_except_image_pools (assembly)) - mono_assembly_close_finish (assembly); -} - -MonoImage* -mono_assembly_load_module (MonoAssembly *assembly, guint32 idx) -{ - return mono_image_load_file_for_image (assembly->image, idx); -} - -/** - * mono_assembly_foreach: - * @func: function to invoke for each assembly loaded - * @user_data: data passed to the callback - * - * Invokes the provided @func callback for each assembly loaded into - * the runtime. The first parameter passed to the callback is the - * `MonoAssembly*`, and the second parameter is the @user_data. - * - * This is done for all assemblies loaded in the runtime, not just - * those loaded in the current application domain. - */ -void -mono_assembly_foreach (GFunc func, gpointer user_data) -{ - GList *copy; - - /* - * We make a copy of the list to avoid calling the callback inside the - * lock, which could lead to deadlocks. - */ - mono_assemblies_lock (); - copy = g_list_copy (loaded_assemblies); - mono_assemblies_unlock (); - - g_list_foreach (loaded_assemblies, func, user_data); - - g_list_free (copy); -} - -/** - * mono_assemblies_cleanup: - * - * Free all resources used by this module. - */ -void -mono_assemblies_cleanup (void) -{ - GSList *l; - - mono_os_mutex_destroy (&assemblies_mutex); - mono_os_mutex_destroy (&assembly_binding_mutex); - - for (l = loaded_assembly_bindings; l; l = l->next) { - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)l->data; - - mono_assembly_binding_info_free (info); - g_free (info); - } - g_slist_free (loaded_assembly_bindings); - - free_assembly_load_hooks (); - free_assembly_search_hooks (); - free_assembly_preload_hooks (); -} - -/*LOCKING takes the assembly_binding lock*/ -void -mono_assembly_cleanup_domain_bindings (guint32 domain_id) -{ - GSList **iter; - - mono_assembly_binding_lock (); - iter = &loaded_assembly_bindings; - while (*iter) { - GSList *l = *iter; - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)l->data; - - if (info->domain_id == domain_id) { - *iter = l->next; - mono_assembly_binding_info_free (info); - g_free (info); - g_slist_free_1 (l); - } else { - iter = &l->next; - } - } - mono_assembly_binding_unlock (); -} - -/* - * Holds the assembly of the application, for - * System.Diagnostics.Process::MainModule - */ -static MonoAssembly *main_assembly=NULL; - -void -mono_assembly_set_main (MonoAssembly *assembly) -{ - main_assembly = assembly; -} - -/** - * mono_assembly_get_main: - * - * Returns: the assembly for the application, the first assembly that is loaded by the VM - */ -MonoAssembly * -mono_assembly_get_main (void) -{ - return (main_assembly); -} - -/** - * mono_assembly_get_image: - * @assembly: The assembly to retrieve the image from - * - * Returns: the MonoImage associated with this assembly. - */ -MonoImage* -mono_assembly_get_image (MonoAssembly *assembly) -{ - return assembly->image; -} - -/** - * mono_assembly_get_name: - * @assembly: The assembly to retrieve the name from - * - * The returned name's lifetime is the same as @assembly's. - * - * Returns: the MonoAssemblyName associated with this assembly. - */ -MonoAssemblyName * -mono_assembly_get_name (MonoAssembly *assembly) -{ - return &assembly->aname; -} - -void -mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies) -{ - bundles = assemblies; -} - -#define MONO_DECLSEC_FORMAT_10 0x3C -#define MONO_DECLSEC_FORMAT_20 0x2E -#define MONO_DECLSEC_FIELD 0x53 -#define MONO_DECLSEC_PROPERTY 0x54 - -#define SKIP_VISIBILITY_XML_ATTRIBUTE ("\"SkipVerification\"") -#define SKIP_VISIBILITY_ATTRIBUTE_NAME ("System.Security.Permissions.SecurityPermissionAttribute") -#define SKIP_VISIBILITY_ATTRIBUTE_SIZE (sizeof (SKIP_VISIBILITY_ATTRIBUTE_NAME) - 1) -#define SKIP_VISIBILITY_PROPERTY_NAME ("SkipVerification") -#define SKIP_VISIBILITY_PROPERTY_SIZE (sizeof (SKIP_VISIBILITY_PROPERTY_NAME) - 1) - -static gboolean -mono_assembly_try_decode_skip_verification_param (const char *p, const char **resp, gboolean *abort_decoding) -{ - int len; - switch (*p++) { - case MONO_DECLSEC_PROPERTY: - break; - case MONO_DECLSEC_FIELD: - default: - *abort_decoding = TRUE; - return FALSE; - break; - } - - if (*p++ != MONO_TYPE_BOOLEAN) { - *abort_decoding = TRUE; - return FALSE; - } - - /* property name length */ - len = mono_metadata_decode_value (p, &p); - - if (len >= SKIP_VISIBILITY_PROPERTY_SIZE && !memcmp (p, SKIP_VISIBILITY_PROPERTY_NAME, SKIP_VISIBILITY_PROPERTY_SIZE)) { - p += len; - return *p; - } - p += len + 1; - - *resp = p; - return FALSE; -} - -static gboolean -mono_assembly_try_decode_skip_verification (const char *p, const char *endn) -{ - int i, j, num, len, params_len; - - if (*p == MONO_DECLSEC_FORMAT_10) { - gsize read, written; - char *res = g_convert (p, endn - p, "UTF-8", "UTF-16LE", &read, &written, NULL); - if (res) { - gboolean found = strstr (res, SKIP_VISIBILITY_XML_ATTRIBUTE) != NULL; - g_free (res); - return found; - } - return FALSE; - } - if (*p++ != MONO_DECLSEC_FORMAT_20) - return FALSE; - - /* number of encoded permission attributes */ - num = mono_metadata_decode_value (p, &p); - for (i = 0; i < num; ++i) { - gboolean is_valid = FALSE; - gboolean abort_decoding = FALSE; - - /* attribute name length */ - len = mono_metadata_decode_value (p, &p); - - /* We don't really need to fully decode the type. Comparing the name is enough */ - is_valid = len >= SKIP_VISIBILITY_ATTRIBUTE_SIZE && !memcmp (p, SKIP_VISIBILITY_ATTRIBUTE_NAME, SKIP_VISIBILITY_ATTRIBUTE_SIZE); - - p += len; - - /*size of the params table*/ - params_len = mono_metadata_decode_value (p, &p); - if (is_valid) { - const char *params_end = p + params_len; - - /* number of parameters */ - len = mono_metadata_decode_value (p, &p); - - for (j = 0; j < len; ++j) { - if (mono_assembly_try_decode_skip_verification_param (p, &p, &abort_decoding)) - return TRUE; - if (abort_decoding) - break; - } - p = params_end; - } else { - p += params_len; - } - } - - return FALSE; -} - - -gboolean -mono_assembly_has_skip_verification (MonoAssembly *assembly) -{ - MonoTableInfo *t; - guint32 cols [MONO_DECL_SECURITY_SIZE]; - const char *blob; - int i, len; - - if (MONO_SECMAN_FLAG_INIT (assembly->skipverification)) - return MONO_SECMAN_FLAG_GET_VALUE (assembly->skipverification); - - t = &assembly->image->tables [MONO_TABLE_DECLSECURITY]; - - for (i = 0; i < t->rows; ++i) { - mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE); - if ((cols [MONO_DECL_SECURITY_PARENT] & MONO_HAS_DECL_SECURITY_MASK) != MONO_HAS_DECL_SECURITY_ASSEMBLY) - continue; - if (cols [MONO_DECL_SECURITY_ACTION] != SECURITY_ACTION_REQMIN) - continue; - - blob = mono_metadata_blob_heap (assembly->image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); - len = mono_metadata_decode_blob_size (blob, &blob); - if (!len) - continue; - - if (mono_assembly_try_decode_skip_verification (blob, blob + len)) { - MONO_SECMAN_FLAG_SET_VALUE (assembly->skipverification, TRUE); - return TRUE; - } - } - - MONO_SECMAN_FLAG_SET_VALUE (assembly->skipverification, FALSE); - return FALSE; -} diff --git a/mono/metadata/assembly.c.REMOVED.git-id b/mono/metadata/assembly.c.REMOVED.git-id new file mode 100644 index 0000000000..ae1e118c37 --- /dev/null +++ b/mono/metadata/assembly.c.REMOVED.git-id @@ -0,0 +1 @@ +7bd02ff37eea77a111cb30ce2d3b64953d487736 \ No newline at end of file diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 41510b486e..71f8fa92ca 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -424,7 +424,6 @@ on_gc_notification (GC_EventType event) switch (e) { case MONO_GC_EVENT_PRE_STOP_WORLD: MONO_GC_WORLD_STOP_BEGIN (); - mono_thread_info_suspend_lock (); break; case MONO_GC_EVENT_POST_STOP_WORLD: @@ -437,7 +436,6 @@ on_gc_notification (GC_EventType event) case MONO_GC_EVENT_POST_START_WORLD: MONO_GC_WORLD_RESTART_END (1); - mono_thread_info_suspend_unlock (); break; case MONO_GC_EVENT_START: @@ -477,7 +475,21 @@ on_gc_notification (GC_EventType event) } mono_profiler_gc_event (e, 0); + + switch (e) { + case MONO_GC_EVENT_PRE_STOP_WORLD: + mono_thread_info_suspend_lock (); + mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0); + break; + case MONO_GC_EVENT_POST_START_WORLD: + mono_thread_info_suspend_unlock (); + mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0); + break; + default: + break; + } } + static void on_gc_heap_resize (size_t new_size) @@ -769,7 +781,7 @@ mono_gc_invoke_finalizers (void) return 0; } -gboolean +MonoBoolean mono_gc_pending_finalizers (void) { return GC_should_invoke_finalizers (); diff --git a/mono/metadata/class.c.REMOVED.git-id b/mono/metadata/class.c.REMOVED.git-id index aeea9c5019..fe47ef994f 100644 --- a/mono/metadata/class.c.REMOVED.git-id +++ b/mono/metadata/class.c.REMOVED.git-id @@ -1 +1 @@ -17da478b5e9c1f089d76de0bc275da6ab5e21077 \ No newline at end of file +56e12ad673e2765956a4fc89dade62a15656a02f \ No newline at end of file diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index a3989ab74a..5a4269b6d8 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -697,4 +697,8 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT void mono_context_init_checked (MonoDomain *domain, MonoError *error); +gboolean +mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error); + + #endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */ diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index a3ba4a76e0..93aced664f 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -807,6 +807,16 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_profiler_appdomain_name (domain, domain->friendly_name); + /* Have to do this quite late so that we at least have System.Object */ + MonoError custom_attr_error; + if (mono_assembly_get_reference_assembly_attribute (ass, &custom_attr_error)) { + char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL); + g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.", corlib_file); + g_free (corlib_file); + exit (1); + } + mono_error_assert_ok (&custom_attr_error); + return domain; } diff --git a/mono/metadata/gc-internals.h b/mono/metadata/gc-internals.h index b5a19af282..cd9408df98 100644 --- a/mono/metadata/gc-internals.h +++ b/mono/metadata/gc-internals.h @@ -145,10 +145,6 @@ void mono_gchandle_free_domain (MonoDomain *domain); typedef void (*FinalizerThreadCallback) (gpointer user_data); -/* if there are finalizers to run, run them. Returns the number of finalizers run */ -gboolean mono_gc_pending_finalizers (void); -void mono_gc_finalize_notify (void); - void* mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size); void* mono_gc_alloc_obj (MonoVTable *vtable, size_t size); void* mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length); diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index c3d240c0d7..a027969e61 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -263,8 +263,12 @@ mono_gc_run_finalize (void *obj, void *data) if (log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o); + mono_profiler_gc_finalize_object_begin (o); + runtime_invoke (o, NULL, &exc, NULL); + mono_profiler_gc_finalize_object_end (o); + if (log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o); @@ -779,11 +783,15 @@ finalizer_thread (gpointer unused) } } + mono_profiler_gc_finalize_begin (); + /* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup), * before the domain is unloaded. */ mono_gc_invoke_finalizers (); + mono_profiler_gc_finalize_end (); + mono_threads_join_threads (); reference_queue_proccess_all (); diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c index e94b73d590..6ffff1a6b7 100644 --- a/mono/metadata/jit-info.c +++ b/mono/metadata/jit-info.c @@ -195,7 +195,7 @@ jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointe while (left < right) { int pos = (left + right) / 2; - MonoJitInfo *ji = (MonoJitInfo *)get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); + MonoJitInfo *ji = (MonoJitInfo *)mono_get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); gint8 *code_end = (gint8*)ji->code_start + ji->code_size; if (addr < code_end) @@ -228,7 +228,7 @@ jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos]; while (pos < chunk->num_elements) { - ji = (MonoJitInfo *)get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); + ji = (MonoJitInfo *)mono_get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); ++pos; @@ -286,7 +286,7 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ table by a hazard pointer and make sure that the pointer is still there after we've made it hazardous, we don't have to worry about the writer freeing the table. */ - table = (MonoJitInfoTable *)get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); + table = (MonoJitInfoTable *)mono_get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); ji = jit_info_table_find (table, hp, (gint8*)addr); if (hp) @@ -298,7 +298,7 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ /* Maybe its an AOT module */ if (try_aot && mono_get_root_domain () && mono_get_root_domain ()->aot_modules) { - table = (MonoJitInfoTable *)get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX); + table = (MonoJitInfoTable *)mono_get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX); module_ji = jit_info_table_find (table, hp, (gint8*)addr); if (module_ji) ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr); diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index 80261f2b62..39ef20082c 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -91,6 +91,39 @@ #endif #endif +/** + * mono_config_get_os: + * + * Returns the operating system that Mono is running on, as used for dllmap entries. + */ +const char * +mono_config_get_os (void) +{ + return CONFIG_OS; +} + +/** + * mono_config_get_cpu: + * + * Returns the architecture that Mono is running on, as used for dllmap entries. + */ +const char * +mono_config_get_cpu (void) +{ + return CONFIG_CPU; +} + +/** + * mono_config_get_wordsize: + * + * Returns the word size that Mono is running on, as used for dllmap entries. + */ +const char * +mono_config_get_wordsize (void) +{ + return CONFIG_WORDSIZE; +} + static void start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, diff --git a/mono/metadata/mono-config.h b/mono/metadata/mono-config.h index 4e68b8a15d..b9695c14ba 100644 --- a/mono/metadata/mono-config.h +++ b/mono/metadata/mono-config.h @@ -13,6 +13,10 @@ MONO_BEGIN_DECLS +MONO_API const char *mono_config_get_os (void); +MONO_API const char *mono_config_get_cpu (void); +MONO_API const char *mono_config_get_wordsize (void); + MONO_API const char* mono_get_config_dir (void); MONO_API void mono_set_config_dir (const char *dir); diff --git a/mono/metadata/mono-gc.h b/mono/metadata/mono-gc.h index e145514869..c5c65b6694 100644 --- a/mono/metadata/mono-gc.h +++ b/mono/metadata/mono-gc.h @@ -50,6 +50,8 @@ MONO_API int mono_gc_get_generation (MonoObject *object); MONO_API int mono_gc_collection_count (int generation); MONO_API int64_t mono_gc_get_used_size (void); MONO_API int64_t mono_gc_get_heap_size (void); +MONO_API MonoBoolean mono_gc_pending_finalizers (void); +MONO_API void mono_gc_finalize_notify (void); MONO_API int mono_gc_invoke_finalizers (void); /* heap walking is only valid in the pre-stop-world event callback */ MONO_API int mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data); diff --git a/mono/metadata/profiler-private.h b/mono/metadata/profiler-private.h index 5888b90fca..1bf80e2c86 100644 --- a/mono/metadata/profiler-private.h +++ b/mono/metadata/profiler-private.h @@ -75,6 +75,11 @@ void mono_profiler_gc_moves (void **objects, int num); void mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj); void mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *extra_info); +void mono_profiler_gc_finalize_begin (void); +void mono_profiler_gc_finalize_object_begin (MonoObject *obj); +void mono_profiler_gc_finalize_object_end (MonoObject *obj); +void mono_profiler_gc_finalize_end (void); + void mono_profiler_code_chunk_new (gpointer chunk, int size); void mono_profiler_code_chunk_destroy (gpointer chunk); void mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data); diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index 4920694b73..fb4cdeca08 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -102,6 +102,11 @@ struct _ProfilerDesc { MonoProfileGCHandleFunc gc_handle; MonoProfileGCRootFunc gc_roots; + MonoProfileGCFinalizeFunc gc_finalize_begin; + MonoProfileGCFinalizeObjectFunc gc_finalize_object_begin; + MonoProfileGCFinalizeObjectFunc gc_finalize_object_end; + MonoProfileGCFinalizeFunc gc_finalize_end; + MonoProfileFunc runtime_initialized_event; MonoProfilerCodeChunkNew code_chunk_new; @@ -925,6 +930,50 @@ mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoPro prof_list->gc_roots = roots_callback; } +void +mono_profiler_gc_finalize_begin (void) +{ + for (ProfilerDesc *prof = prof_list; prof; prof = prof->next) + if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_begin) + prof->gc_finalize_begin (prof->profiler); +} + +void +mono_profiler_gc_finalize_object_begin (MonoObject *obj) +{ + for (ProfilerDesc *prof = prof_list; prof; prof = prof->next) + if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_begin) + prof->gc_finalize_object_begin (prof->profiler, obj); +} + +void +mono_profiler_gc_finalize_object_end (MonoObject *obj) +{ + for (ProfilerDesc *prof = prof_list; prof; prof = prof->next) + if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_end) + prof->gc_finalize_object_end (prof->profiler, obj); +} + +void +mono_profiler_gc_finalize_end (void) +{ + for (ProfilerDesc *prof = prof_list; prof; prof = prof->next) + if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_end) + prof->gc_finalize_end (prof->profiler); +} + +void +mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end) +{ + if (!prof_list) + return; + + prof_list->gc_finalize_begin = begin; + prof_list->gc_finalize_object_begin = begin_obj; + prof_list->gc_finalize_object_begin = end_obj; + prof_list->gc_finalize_end = end; +} + void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback) { diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h index b793548ef8..84dc1bb83b 100644 --- a/mono/metadata/profiler.h +++ b/mono/metadata/profiler.h @@ -31,7 +31,8 @@ typedef enum { MONO_PROFILE_IOMAP_EVENTS = 1 << 18, /* this should likely be removed, too */ MONO_PROFILE_GC_MOVES = 1 << 19, MONO_PROFILE_GC_ROOTS = 1 << 20, - MONO_PROFILE_CONTEXT_EVENTS = 1 << 21 + MONO_PROFILE_CONTEXT_EVENTS = 1 << 21, + MONO_PROFILE_GC_FINALIZATION = 1 << 22 } MonoProfileFlags; typedef enum { @@ -39,6 +40,7 @@ typedef enum { MONO_PROFILE_FAILED } MonoProfileResult; +// Keep somewhat in sync with libgc/include/gc.h:enum GC_EventType typedef enum { MONO_GC_EVENT_START, MONO_GC_EVENT_MARK_START, @@ -46,10 +48,26 @@ typedef enum { MONO_GC_EVENT_RECLAIM_START, MONO_GC_EVENT_RECLAIM_END, MONO_GC_EVENT_END, + /* + * This is the actual arrival order of the following events: + * + * MONO_GC_EVENT_PRE_STOP_WORLD + * MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED + * MONO_GC_EVENT_POST_STOP_WORLD + * MONO_GC_EVENT_PRE_START_WORLD + * MONO_GC_EVENT_POST_START_WORLD_UNLOCKED + * MONO_GC_EVENT_POST_START_WORLD + * + * The LOCKED and UNLOCKED events guarantee that, by the time they arrive, + * the GC and suspend locks will both have been acquired and released, + * respectively. + */ MONO_GC_EVENT_PRE_STOP_WORLD, MONO_GC_EVENT_POST_STOP_WORLD, MONO_GC_EVENT_PRE_START_WORLD, - MONO_GC_EVENT_POST_START_WORLD + MONO_GC_EVENT_POST_START_WORLD, + MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, + MONO_GC_EVENT_POST_START_WORLD_UNLOCKED } MonoGCEvent; /* coverage info */ @@ -150,6 +168,9 @@ typedef void (*MonoProfileGCResizeFunc) (MonoProfiler *prof, int64_t new_size) typedef void (*MonoProfileGCHandleFunc) (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj); typedef void (*MonoProfileGCRootFunc) (MonoProfiler *prof, int num_roots, void **objects, int *root_types, uintptr_t *extra_info); +typedef void (*MonoProfileGCFinalizeFunc) (MonoProfiler *prof); +typedef void (*MonoProfileGCFinalizeObjectFunc) (MonoProfiler *prof, MonoObject *obj); + typedef void (*MonoProfileIomapFunc) (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname); typedef mono_bool (*MonoProfileCoverageFilterFunc) (MonoProfiler *prof, MonoMethod *method); @@ -197,6 +218,7 @@ MONO_API void mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *metho MONO_API void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback); MONO_API void mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback); MONO_API void mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback); +MONO_API void mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end); MONO_API void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback); MONO_API void mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback); diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 7485ac5ffd..7bfe3c4e60 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -490,7 +490,7 @@ mono_gc_invoke_finalizers (void) return sgen_gc_invoke_finalizers (); } -gboolean +MonoBoolean mono_gc_pending_finalizers (void) { return sgen_have_pending_finalizers (); diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index ea14448ccf..60e5933450 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -209,6 +209,8 @@ sgen_client_stop_world (int generation) acquire_gc_locks (); + mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation); + /* We start to scan after locks are taking, this ensures we won't be interrupted. */ sgen_process_togglerefs (); @@ -283,6 +285,8 @@ sgen_client_restart_world (int generation, gint64 *stw_time) */ release_gc_locks (); + mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation); + *stw_time = usec; } diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index 5b0b72b051..ebba9e0bc1 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -824,7 +824,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.6.0.182/3ed2bba\"" > version.h + echo "#define FULL_VERSION \"Stable 4.6.0.243/dea2155\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 5b0b72b051..ebba9e0bc1 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -824,7 +824,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.6.0.182/3ed2bba\"" > version.h + echo "#define FULL_VERSION \"Stable 4.6.0.243/dea2155\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index 4069a46d6d..4c88e3aeeb 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -95fb4f0f463f11376bc66366d33b0ada31e655e7 \ No newline at end of file +573c53e6293cd2939965dca9b67122cfc812637e \ No newline at end of file diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 39abeb2854..2a12aecb6f 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -1883,3 +1883,8 @@ mono_throw_method_access (MonoMethod *callee, MonoMethod *caller) g_free (callee_name); g_free (caller_name); } + +void +mono_dummy_jit_icall (void) +{ +} diff --git a/mono/mini/jit-icalls.h b/mono/mini/jit-icalls.h index 319ec902a0..9d8deb2619 100644 --- a/mono/mini/jit-icalls.h +++ b/mono/mini/jit-icalls.h @@ -226,4 +226,6 @@ double mono_ckfinite (double d); void mono_throw_method_access (MonoMethod *callee, MonoMethod *caller); +void mono_dummy_jit_icall (void); + #endif /* __MONO_JIT_ICALLS_H__ */ diff --git a/mono/mini/method-to-ir.c.REMOVED.git-id b/mono/mini/method-to-ir.c.REMOVED.git-id index 8831a55563..c21985b8ef 100644 --- a/mono/mini/method-to-ir.c.REMOVED.git-id +++ b/mono/mini/method-to-ir.c.REMOVED.git-id @@ -1 +1 @@ -3bcf4cb71650d65d78892cb857793dfc5e9ff723 \ No newline at end of file +a907decc82e6ebd6fbd2f02741729d50fcfe07b4 \ No newline at end of file diff --git a/mono/mini/mini-amd64.c.REMOVED.git-id b/mono/mini/mini-amd64.c.REMOVED.git-id index df52ba956e..7b364b9eb5 100644 --- a/mono/mini/mini-amd64.c.REMOVED.git-id +++ b/mono/mini/mini-amd64.c.REMOVED.git-id @@ -1 +1 @@ -aa7acf5abc72eb26d1200dce837653f7885f2eab \ No newline at end of file +3f41fb3fc226e85aa23b373990dd4e5738d6d28d \ No newline at end of file diff --git a/mono/mini/mini-arm.c.REMOVED.git-id b/mono/mini/mini-arm.c.REMOVED.git-id index 48a33e6782..e996b06490 100644 --- a/mono/mini/mini-arm.c.REMOVED.git-id +++ b/mono/mini/mini-arm.c.REMOVED.git-id @@ -1 +1 @@ -a708eb3eb22b244fef50931de958816f2d0f4ece \ No newline at end of file +2eac36939370f203a0ed0b3ea7e284bc90b21527 \ No newline at end of file diff --git a/mono/mini/mini-ia64.c.REMOVED.git-id b/mono/mini/mini-ia64.c.REMOVED.git-id index 7c3622ce23..fcba747b1d 100644 --- a/mono/mini/mini-ia64.c.REMOVED.git-id +++ b/mono/mini/mini-ia64.c.REMOVED.git-id @@ -1 +1 @@ -d88a6c99a8f362bb690424ace4462d58f3d913d9 \ No newline at end of file +357e260799833ed8d4a1bf415c148853bf610e39 \ No newline at end of file diff --git a/mono/mini/mini-llvm.c.REMOVED.git-id b/mono/mini/mini-llvm.c.REMOVED.git-id index 29e04d074a..f5f4db2ac7 100644 --- a/mono/mini/mini-llvm.c.REMOVED.git-id +++ b/mono/mini/mini-llvm.c.REMOVED.git-id @@ -1 +1 @@ -2fe69c378a64914c4bb35bf1a52a00153609255b \ No newline at end of file +1bf1ba6fa13f613a176781c0d4a9c16183273460 \ No newline at end of file diff --git a/mono/mini/mini-mips.c.REMOVED.git-id b/mono/mini/mini-mips.c.REMOVED.git-id index d628c90d15..62f3c3bdb3 100644 --- a/mono/mini/mini-mips.c.REMOVED.git-id +++ b/mono/mini/mini-mips.c.REMOVED.git-id @@ -1 +1 @@ -5d6ebc7b6bc126975df54bdc38c29d247d5ca8d0 \ No newline at end of file +783896f15681743acb6001dad302705db271bee9 \ No newline at end of file diff --git a/mono/mini/mini-ppc.c.REMOVED.git-id b/mono/mini/mini-ppc.c.REMOVED.git-id index cbf58a91de..c4e4e26fbf 100644 --- a/mono/mini/mini-ppc.c.REMOVED.git-id +++ b/mono/mini/mini-ppc.c.REMOVED.git-id @@ -1 +1 @@ -3089a8546b1d3a4d605535a775c1f57d27eb793f \ No newline at end of file +7d2c0d8b8cfda73cacd3b6847b37f7c5dd523da4 \ No newline at end of file diff --git a/mono/mini/mini-runtime.c.REMOVED.git-id b/mono/mini/mini-runtime.c.REMOVED.git-id index 011fc99152..7429fe535f 100644 --- a/mono/mini/mini-runtime.c.REMOVED.git-id +++ b/mono/mini/mini-runtime.c.REMOVED.git-id @@ -1 +1 @@ -352a868b87f98ab2000dd24c33320aee1b63b2a5 \ No newline at end of file +c4ae82e0cbcbda75f4f963ba3f352e7d90dc4c14 \ No newline at end of file diff --git a/mono/mini/mini-s390x.c.REMOVED.git-id b/mono/mini/mini-s390x.c.REMOVED.git-id index 818840029c..e83851c357 100644 --- a/mono/mini/mini-s390x.c.REMOVED.git-id +++ b/mono/mini/mini-s390x.c.REMOVED.git-id @@ -1 +1 @@ -3fe40d2cfc28fdd8a055b003ad58785d5cbd3427 \ No newline at end of file +a1094afa173fbe0baeb75c2ff221e0e9b73ae7e9 \ No newline at end of file diff --git a/mono/mini/mini-sparc.c.REMOVED.git-id b/mono/mini/mini-sparc.c.REMOVED.git-id index 9fe33be54e..c3981222a3 100644 --- a/mono/mini/mini-sparc.c.REMOVED.git-id +++ b/mono/mini/mini-sparc.c.REMOVED.git-id @@ -1 +1 @@ -022f8a5e790b8ea9334d4fa61bb7f92c99229c9f \ No newline at end of file +5003bfe025403fa2d02c9709b18d04fa2e26b491 \ No newline at end of file diff --git a/mono/mini/mini-x86.c.REMOVED.git-id b/mono/mini/mini-x86.c.REMOVED.git-id index 8946a7a486..216bd0b682 100644 --- a/mono/mini/mini-x86.c.REMOVED.git-id +++ b/mono/mini/mini-x86.c.REMOVED.git-id @@ -1 +1 @@ -badf12b33b3bf1d72f1466b48e8c8a0aeb517e88 \ No newline at end of file +6a3a6c0aa4e1c0a792e0d4bcc355138b97d67f68 \ No newline at end of file diff --git a/mono/mini/version.h b/mono/mini/version.h index 4ce6e3b414..8e54e10ae6 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 4.6.0.182/3ed2bba" +#define FULL_VERSION "Stable 4.6.0.243/dea2155" diff --git a/mono/profiler/decode.c.REMOVED.git-id b/mono/profiler/decode.c.REMOVED.git-id index b466bdd7f6..b2162e6edd 100644 --- a/mono/profiler/decode.c.REMOVED.git-id +++ b/mono/profiler/decode.c.REMOVED.git-id @@ -1 +1 @@ -e8d53afea686ed76588370c99fe74beac2c0718b \ No newline at end of file +b213528caaa35b55a02a43f0c8b2329a40eeab75 \ No newline at end of file diff --git a/mono/profiler/proflog.c.REMOVED.git-id b/mono/profiler/proflog.c.REMOVED.git-id index 8cd1ef669d..dfe3506712 100644 --- a/mono/profiler/proflog.c.REMOVED.git-id +++ b/mono/profiler/proflog.c.REMOVED.git-id @@ -1 +1 @@ -99e68567571dcf59b3759f143d2642e0861c06de \ No newline at end of file +40e4187280464b96aac6aa5ea5d1f8539689ea02 \ No newline at end of file diff --git a/mono/profiler/proflog.h b/mono/profiler/proflog.h index ecb0e43b82..5649d8be76 100644 --- a/mono/profiler/proflog.h +++ b/mono/profiler/proflog.h @@ -3,10 +3,14 @@ #define BUF_ID 0x4D504C01 #define LOG_HEADER_ID 0x4D505A01 -#define LOG_VERSION_MAJOR 0 -#define LOG_VERSION_MINOR 4 -#define LOG_DATA_VERSION 12 +#define LOG_VERSION_MAJOR 1 +#define LOG_VERSION_MINOR 0 +#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 @@ -27,6 +31,32 @@ 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 { @@ -40,6 +70,7 @@ enum { TYPE_SAMPLE, TYPE_RUNTIME, TYPE_COVERAGE, + TYPE_META, /* extended type for TYPE_HEAP */ TYPE_HEAP_START = 0 << 4, TYPE_HEAP_END = 1 << 4, @@ -48,13 +79,6 @@ enum { /* extended type for TYPE_METADATA */ TYPE_END_LOAD = 2 << 4, TYPE_END_UNLOAD = 4 << 4, - /* metadata type byte for TYPE_METADATA */ - TYPE_CLASS = 1, - TYPE_IMAGE = 2, - TYPE_ASSEMBLY = 3, - TYPE_DOMAIN = 4, - TYPE_THREAD = 5, - TYPE_CONTEXT = 6, /* extended type for TYPE_GC */ TYPE_GC_EVENT = 1 << 4, TYPE_GC_RESIZE = 2 << 4, @@ -63,15 +87,19 @@ enum { 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 = 0 << 4, - TYPE_CLAUSE = 1 << 4, - TYPE_EXCEPTION_BT = 1 << 7, + 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, @@ -91,9 +119,27 @@ enum { 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 { diff --git a/mono/profiler/utils.c b/mono/profiler/utils.c index 753024dcf7..c3e14e4af8 100644 --- a/mono/profiler/utils.c +++ b/mono/profiler/utils.c @@ -418,7 +418,7 @@ uintptr_t process_id (void) { #ifdef HOST_WIN32 - return 0; /* FIXME */ + return GetCurrentProcessId (); #else return (uintptr_t)getpid (); #endif diff --git a/mono/sgen/sgen-marksweep.c b/mono/sgen/sgen-marksweep.c index 322bc9b51b..56dba1b0ee 100644 --- a/mono/sgen/sgen-marksweep.c +++ b/mono/sgen/sgen-marksweep.c @@ -1144,10 +1144,7 @@ major_get_and_reset_num_major_objects_marked (void) /* gcc 4.2.1 from xcode4 crashes on sgen_card_table_get_card_address () when this is enabled */ #if defined(PLATFORM_MACOSX) -#define GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) -#if GCC_VERSION <= 40300 +#if MONO_GNUC_VERSION <= 40300 #undef PREFETCH_CARDS #endif #endif diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index cf5eada2f4..f0f7def44b 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -436,7 +436,8 @@ BASE_TEST_CS_SRC= \ pinvoke_ppci.cs \ pinvoke_ppcf.cs \ pinvoke_ppcd.cs \ - bug-29585.cs + bug-29585.cs \ + reference-loader.cs TEST_CS_SRC_DIST= \ $(BASE_TEST_CS_SRC) \ @@ -700,11 +701,13 @@ TEST_IL_SRC= \ # but that need to be compiled PREREQ_IL_SRC=event-il.il module-cctor.il PREREQ_CS_SRC= -PREREQ_IL_DLL_SRC=event-il.il module-cctor.il -PREREQ_CS_DLL_SRC= +PREREQ_IL_DLL_SRC= +PREREQ_CS_DLL_SRC=TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs -PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) -PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) +PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) \ + $(PREREQ_IL_DLL_SRC:.il=.dll) +PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll) TESTSI_CS=$(TEST_CS_SRC:.cs=.exe) TESTSI_IL=$(TEST_IL_SRC:.il=.exe) TESTBS=$(BENCHSRC:.cs=.exe) @@ -719,6 +722,13 @@ EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \ %.exe: %.cs TestDriver.dll $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $< +%.dll: %.cs + $(MCS) -r:System.dll -target:library -out:$@ $< + +TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll + $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $< + + # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test if POWERPC test_platform: diff --git a/mono/tests/Makefile.in b/mono/tests/Makefile.in index 62dba2054e..bd17f8e130 100644 --- a/mono/tests/Makefile.in +++ b/mono/tests/Makefile.in @@ -842,7 +842,8 @@ BASE_TEST_CS_SRC = \ pinvoke_ppci.cs \ pinvoke_ppcf.cs \ pinvoke_ppcd.cs \ - bug-29585.cs + bug-29585.cs \ + reference-loader.cs TEST_CS_SRC_DIST = \ $(BASE_TEST_CS_SRC) \ @@ -1056,10 +1057,14 @@ TEST_IL_SRC = \ # but that need to be compiled PREREQ_IL_SRC = event-il.il module-cctor.il PREREQ_CS_SRC = -PREREQ_IL_DLL_SRC = event-il.il module-cctor.il -PREREQ_CS_DLL_SRC = -PREREQSI_IL = $(PREREQ_IL_SRC:.il=.exe) -PREREQSI_CS = $(PREREQ_CS_SRC:.cs=.exe) +PREREQ_IL_DLL_SRC = +PREREQ_CS_DLL_SRC = TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs +PREREQSI_IL = $(PREREQ_IL_SRC:.il=.exe) \ + $(PREREQ_IL_DLL_SRC:.il=.dll) + +PREREQSI_CS = $(PREREQ_CS_SRC:.cs=.exe) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll) + TESTSI_CS = $(TEST_CS_SRC:.cs=.exe) TESTSI_IL = $(TEST_IL_SRC:.il=.exe) TESTBS = $(BENCHSRC:.cs=.exe) @@ -1596,6 +1601,12 @@ aotcheck: testaot gshared-aot %.exe: %.cs TestDriver.dll $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $< +%.dll: %.cs + $(MCS) -r:System.dll -target:library -out:$@ $< + +TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll + $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $< + # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test @POWERPC_TRUE@test_platform: # Can't use mkbundle on win32 since there is no static build there diff --git a/mono/tests/reference-loader.cs b/mono/tests/reference-loader.cs new file mode 100644 index 0000000000..9cdda7a719 --- /dev/null +++ b/mono/tests/reference-loader.cs @@ -0,0 +1,111 @@ +// +// reference-loader.cs: +// +// Test for reference assembly loading + +using System; +using System.IO; +using System.Reflection; + +public class Tests { + public static int Main (string[] args) + { + return TestDriver.RunTests (typeof (Tests), args); + } + + public static int test_0_loadFrom_reference () + { + // Check that loading a reference assembly by filename for execution is an error + try { + var a = Assembly.LoadFrom ("./TestingReferenceAssembly.dll"); + } catch (BadImageFormatException exn) { + // Console.Error.WriteLine ("exn was {0}", exn); + return 0; + } + return 1; + } + + public static int test_0_load_reference () + { + // Check that loading a reference assembly for execution is an error + try { + var an = new AssemblyName ("TestingReferenceAssembly"); + var a = Assembly.Load (an); + } catch (BadImageFormatException exn) { + //Console.Error.WriteLine ("exn was {0}", exn); + return 0; + } catch (FileNotFoundException exn) { + Console.Error.WriteLine ("incorrect exn was {0}", exn); + return 2; + } + return 1; + } + + public static int test_0_reflection_load_reference () + { + // Check that reflection-only loading a reference assembly is okay + var an = new AssemblyName ("TestingReferenceAssembly"); + var a = Assembly.ReflectionOnlyLoad (an.FullName); + var t = a.GetType ("X"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + + public static int test_0_load_reference_asm_via_reference () + { + // Check that loading an assembly that references a reference assembly doesn't succeed. + var an = new AssemblyName ("TestingReferenceReferenceAssembly"); + try { + var a = Assembly.Load (an); + var t = a.GetType ("Z"); + } catch (FileNotFoundException){ + return 0; + } + return 1; + } + + public static int test_0_reflection_load_reference_asm_via_reference () + { + // Check that reflection-only loading an assembly that + // references a reference assembly is okay. + var an = new AssemblyName ("TestingReferenceReferenceAssembly"); + var a = Assembly.ReflectionOnlyLoad (an.FullName); + var t = a.GetType ("Z"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + + + public static int test_0_load_reference_bytes () + { + // Check that loading a reference assembly from a byte array for execution is an error + byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll"); + try { + var a = Assembly.Load (bs); + } catch (BadImageFormatException) { + return 0; + } catch (FileNotFoundException exn) { + Console.Error.WriteLine ("incorrect exn was {0}", exn); + return 2; + } + return 1; + } + + public static int test_0_reflection_load_reference_bytes () + { + // Check that loading a reference assembly from a byte + // array for reflection only is okay. + byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll"); + var a = Assembly.ReflectionOnlyLoad (bs); + var t = a.GetType ("X"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + +} diff --git a/mono/unit-tests/test-mono-linked-list-set.c b/mono/unit-tests/test-mono-linked-list-set.c index 3841581e0b..a5e01ebe09 100644 --- a/mono/unit-tests/test-mono-linked-list-set.c +++ b/mono/unit-tests/test-mono-linked-list-set.c @@ -74,11 +74,11 @@ worker (void *arg) break; case STATE_OUT: if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_OUT) == STATE_OUT) { - result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX); + result = mono_lls_find (&lls, hp, i); assert (!result); mono_hazard_pointer_clear_all (hp, -1); - result = mono_lls_insert (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX); + result = mono_lls_insert (&lls, hp, &nodes [i].node); mono_hazard_pointer_clear_all (hp, -1); assert (nodes [i].state == STATE_BUSY); @@ -89,12 +89,12 @@ worker (void *arg) break; case STATE_IN: if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_IN) == STATE_IN) { - result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX); + result = mono_lls_find (&lls, hp, i); assert (result); assert (mono_hazard_pointer_get_val (hp, 1) == &nodes [i].node); mono_hazard_pointer_clear_all (hp, -1); - result = mono_lls_remove (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX); + result = mono_lls_remove (&lls, hp, &nodes [i].node); mono_hazard_pointer_clear_all (hp, -1); ++thread_data->num_removes; @@ -126,7 +126,7 @@ main (int argc, char *argv []) mono_threads_init (&thread_callbacks, 0); - mono_lls_init (&lls, free_node, HAZARD_FREE_NO_LOCK); + mono_lls_init (&lls, free_node); for (i = 0; i < N; ++i) { nodes [i].node.key = i; diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index b62633307b..ddff14f69e 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -126,6 +126,7 @@ monoutils_sources = \ atomic.c \ mono-hwcap.h \ mono-hwcap.c \ + mono-hwcap-vars.h \ bsearch.h \ bsearch.c \ mono-signal-handler.h \ @@ -176,48 +177,56 @@ arch_sources += mach-support-unknown.c endif +if !CROSS_COMPILE + if X86 -arch_sources += mono-hwcap-x86.c mono-hwcap-x86.h +arch_sources += mono-hwcap-x86.c endif if AMD64 -arch_sources += mono-hwcap-x86.c mono-hwcap-x86.h +arch_sources += mono-hwcap-x86.c endif if ARM -arch_sources += mono-hwcap-arm.c mono-hwcap-arm.h +arch_sources += mono-hwcap-arm.c endif if ARM64 -arch_sources += mono-hwcap-arm64.c mono-hwcap-arm64.h +arch_sources += mono-hwcap-arm64.c endif if MIPS -arch_sources += mono-hwcap-mips.c mono-hwcap-mips.h +arch_sources += mono-hwcap-mips.c endif if POWERPC -arch_sources += mono-hwcap-ppc.c mono-hwcap-ppc.h +arch_sources += mono-hwcap-ppc.c endif if POWERPC64 -arch_sources += mono-hwcap-ppc.c mono-hwcap-ppc.h +arch_sources += mono-hwcap-ppc.c endif if SPARC -arch_sources += mono-hwcap-sparc.c mono-hwcap-sparc.h +arch_sources += mono-hwcap-sparc.c endif if SPARC64 -arch_sources += mono-hwcap-sparc.c mono-hwcap-sparc.h +arch_sources += mono-hwcap-sparc.c endif if IA64 -arch_sources += mono-hwcap-ia64.c mono-hwcap-ia64.h +arch_sources += mono-hwcap-ia64.c endif if S390X -arch_sources += mono-hwcap-s390x.c mono-hwcap-s390x.h +arch_sources += mono-hwcap-s390x.c +endif + +else + +arch_sources += mono-hwcap-cross.c + endif libmonoutils_la_SOURCES = $(monoutils_sources) $(arch_sources) diff --git a/mono/utils/Makefile.in b/mono/utils/Makefile.in index 8951c631d2..ed8f2c552a 100644 --- a/mono/utils/Makefile.in +++ b/mono/utils/Makefile.in @@ -85,17 +85,18 @@ target_triplet = @target@ @ARM_TRUE@@CROSS_COMPILE_FALSE@am__append_3 = mach-support-arm.c @ARM64_TRUE@@CROSS_COMPILE_FALSE@am__append_4 = mach-support-arm64.c @CROSS_COMPILE_TRUE@am__append_5 = mach-support-unknown.c -@X86_TRUE@am__append_6 = mono-hwcap-x86.c mono-hwcap-x86.h -@AMD64_TRUE@am__append_7 = mono-hwcap-x86.c mono-hwcap-x86.h -@ARM_TRUE@am__append_8 = mono-hwcap-arm.c mono-hwcap-arm.h -@ARM64_TRUE@am__append_9 = mono-hwcap-arm64.c mono-hwcap-arm64.h -@MIPS_TRUE@am__append_10 = mono-hwcap-mips.c mono-hwcap-mips.h -@POWERPC_TRUE@am__append_11 = mono-hwcap-ppc.c mono-hwcap-ppc.h -@POWERPC64_TRUE@am__append_12 = mono-hwcap-ppc.c mono-hwcap-ppc.h -@SPARC_TRUE@am__append_13 = mono-hwcap-sparc.c mono-hwcap-sparc.h -@SPARC64_TRUE@am__append_14 = mono-hwcap-sparc.c mono-hwcap-sparc.h -@IA64_TRUE@am__append_15 = mono-hwcap-ia64.c mono-hwcap-ia64.h -@S390X_TRUE@am__append_16 = mono-hwcap-s390x.c mono-hwcap-s390x.h +@CROSS_COMPILE_FALSE@@X86_TRUE@am__append_6 = mono-hwcap-x86.c +@AMD64_TRUE@@CROSS_COMPILE_FALSE@am__append_7 = mono-hwcap-x86.c +@ARM_TRUE@@CROSS_COMPILE_FALSE@am__append_8 = mono-hwcap-arm.c +@ARM64_TRUE@@CROSS_COMPILE_FALSE@am__append_9 = mono-hwcap-arm64.c +@CROSS_COMPILE_FALSE@@MIPS_TRUE@am__append_10 = mono-hwcap-mips.c +@CROSS_COMPILE_FALSE@@POWERPC_TRUE@am__append_11 = mono-hwcap-ppc.c +@CROSS_COMPILE_FALSE@@POWERPC64_TRUE@am__append_12 = mono-hwcap-ppc.c +@CROSS_COMPILE_FALSE@@SPARC_TRUE@am__append_13 = mono-hwcap-sparc.c +@CROSS_COMPILE_FALSE@@SPARC64_TRUE@am__append_14 = mono-hwcap-sparc.c +@CROSS_COMPILE_FALSE@@IA64_TRUE@am__append_15 = mono-hwcap-ia64.c +@CROSS_COMPILE_FALSE@@S390X_TRUE@am__append_16 = mono-hwcap-s390x.c +@CROSS_COMPILE_TRUE@am__append_17 = mono-hwcap-cross.c subdir = mono/utils DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \ @@ -155,20 +156,17 @@ am__libmonoutils_la_SOURCES_DIST = mono-md5.c mono-sha1.c \ mono-threads-posix-abort-syscall.c \ mono-threads-windows-abort-syscall.c mono-tls.h mono-tls.c \ linux_magic.h mono-memory-model.h atomic.h atomic.c \ - mono-hwcap.h mono-hwcap.c bsearch.h bsearch.c \ - mono-signal-handler.h mono-conc-hashtable.h \ + mono-hwcap.h mono-hwcap.c mono-hwcap-vars.h bsearch.h \ + bsearch.c mono-signal-handler.h mono-conc-hashtable.h \ mono-conc-hashtable.c sha1.h sha1.c json.h json.c networking.c \ networking-posix.c networking-fallback.c networking-missing.c \ networking-windows.c networking.h mono-rand.c mono-rand.h \ memfuncs.c memfuncs.h parse.c parse.h checked-build.c \ checked-build.h mach-support-x86.c mach-support-amd64.c \ mach-support-arm.c mach-support-arm64.c mach-support-unknown.c \ - mono-hwcap-x86.c mono-hwcap-x86.h mono-hwcap-arm.c \ - mono-hwcap-arm.h mono-hwcap-arm64.c mono-hwcap-arm64.h \ - mono-hwcap-mips.c mono-hwcap-mips.h mono-hwcap-ppc.c \ - mono-hwcap-ppc.h mono-hwcap-sparc.c mono-hwcap-sparc.h \ - mono-hwcap-ia64.c mono-hwcap-ia64.h mono-hwcap-s390x.c \ - mono-hwcap-s390x.h + mono-hwcap-x86.c mono-hwcap-arm.c mono-hwcap-arm64.c \ + mono-hwcap-mips.c mono-hwcap-ppc.c mono-hwcap-sparc.c \ + mono-hwcap-ia64.c mono-hwcap-s390x.c mono-hwcap-cross.c am__objects_1 = mono-md5.lo mono-sha1.lo mono-logger.lo \ mono-codeman.lo dlmalloc.lo mono-counters.lo mono-dl.lo \ mono-dl-windows.lo mono-dl-darwin.lo mono-dl-posix.lo \ @@ -201,24 +199,27 @@ am__objects_1 = mono-md5.lo mono-sha1.lo mono-logger.lo \ @ARM64_TRUE@@CROSS_COMPILE_FALSE@am__objects_5 = \ @ARM64_TRUE@@CROSS_COMPILE_FALSE@ mach-support-arm64.lo @CROSS_COMPILE_TRUE@am__objects_6 = mach-support-unknown.lo -@X86_TRUE@am__objects_7 = mono-hwcap-x86.lo -@AMD64_TRUE@am__objects_8 = mono-hwcap-x86.lo -@ARM_TRUE@am__objects_9 = mono-hwcap-arm.lo -@ARM64_TRUE@am__objects_10 = mono-hwcap-arm64.lo -@MIPS_TRUE@am__objects_11 = mono-hwcap-mips.lo -@POWERPC_TRUE@am__objects_12 = mono-hwcap-ppc.lo -@POWERPC64_TRUE@am__objects_13 = mono-hwcap-ppc.lo -@SPARC_TRUE@am__objects_14 = mono-hwcap-sparc.lo -@SPARC64_TRUE@am__objects_15 = mono-hwcap-sparc.lo -@IA64_TRUE@am__objects_16 = mono-hwcap-ia64.lo -@S390X_TRUE@am__objects_17 = mono-hwcap-s390x.lo -am__objects_18 = $(am__objects_2) $(am__objects_3) $(am__objects_4) \ +@CROSS_COMPILE_FALSE@@X86_TRUE@am__objects_7 = mono-hwcap-x86.lo +@AMD64_TRUE@@CROSS_COMPILE_FALSE@am__objects_8 = mono-hwcap-x86.lo +@ARM_TRUE@@CROSS_COMPILE_FALSE@am__objects_9 = mono-hwcap-arm.lo +@ARM64_TRUE@@CROSS_COMPILE_FALSE@am__objects_10 = mono-hwcap-arm64.lo +@CROSS_COMPILE_FALSE@@MIPS_TRUE@am__objects_11 = mono-hwcap-mips.lo +@CROSS_COMPILE_FALSE@@POWERPC_TRUE@am__objects_12 = mono-hwcap-ppc.lo +@CROSS_COMPILE_FALSE@@POWERPC64_TRUE@am__objects_13 = \ +@CROSS_COMPILE_FALSE@@POWERPC64_TRUE@ mono-hwcap-ppc.lo +@CROSS_COMPILE_FALSE@@SPARC_TRUE@am__objects_14 = mono-hwcap-sparc.lo +@CROSS_COMPILE_FALSE@@SPARC64_TRUE@am__objects_15 = \ +@CROSS_COMPILE_FALSE@@SPARC64_TRUE@ mono-hwcap-sparc.lo +@CROSS_COMPILE_FALSE@@IA64_TRUE@am__objects_16 = mono-hwcap-ia64.lo +@CROSS_COMPILE_FALSE@@S390X_TRUE@am__objects_17 = mono-hwcap-s390x.lo +@CROSS_COMPILE_TRUE@am__objects_18 = mono-hwcap-cross.lo +am__objects_19 = $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) $(am__objects_12) $(am__objects_13) \ $(am__objects_14) $(am__objects_15) $(am__objects_16) \ - $(am__objects_17) -am_libmonoutils_la_OBJECTS = $(am__objects_1) $(am__objects_18) + $(am__objects_17) $(am__objects_18) +am_libmonoutils_la_OBJECTS = $(am__objects_1) $(am__objects_19) libmonoutils_la_OBJECTS = $(am_libmonoutils_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -630,6 +631,7 @@ monoutils_sources = \ atomic.c \ mono-hwcap.h \ mono-hwcap.c \ + mono-hwcap-vars.h \ bsearch.h \ bsearch.c \ mono-signal-handler.h \ @@ -659,7 +661,7 @@ arch_sources = $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ $(am__append_13) $(am__append_14) $(am__append_15) \ - $(am__append_16) + $(am__append_16) $(am__append_17) libmonoutils_la_SOURCES = $(monoutils_sources) $(arch_sources) libmonoutilsincludedir = $(includedir)/mono-$(API_VER)/mono/utils libmonoutilsinclude_HEADERS = \ @@ -754,6 +756,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-filemap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-arm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-arm64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-cross.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-ia64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-mips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-hwcap-ppc.Plo@am__quote@ diff --git a/mono/utils/atomic.h b/mono/utils/atomic.h index 4f5f010afd..dca6170a1a 100755 --- a/mono/utils/atomic.h +++ b/mono/utils/atomic.h @@ -14,6 +14,7 @@ #include "config.h" #include +#include /* The current Nexus 7 arm-v7a fails with: @@ -29,7 +30,6 @@ Apple targets have historically being problematic, xcode 4.6 would miscompile th #define WIN32_LEAN_AND_MEAN #endif #include -#include /* mingw is missing InterlockedCompareExchange64 () from winbase.h */ #if HAVE_DECL_INTERLOCKEDCOMPAREEXCHANGE64==0 @@ -180,30 +180,63 @@ static inline void InterlockedWrite16(volatile gint16 *dst, gint16 val) /* Prefer GCC atomic ops if the target supports it (see configure.ac). */ #elif defined(USE_GCC_ATOMIC_OPS) +/* + * As of this comment (August 2016), all current Clang versions get atomic + * intrinsics on ARM64 wrong. All GCC versions prior to 5.3.0 do, too. The bug + * is the same: The compiler developers thought that the acq + rel barriers + * that ARM64 load/store instructions can impose are sufficient to provide + * sequential consistency semantics. This is not the case: + * + * http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/229588.html + * + * We work around this bug by inserting full barriers around each atomic + * intrinsic if we detect that we're built with a buggy compiler. + */ + +#if defined (HOST_ARM64) && (defined (__clang__) || MONO_GNUC_VERSION < 50300) +#define WRAP_ATOMIC_INTRINSIC(INTRIN) \ + ({ \ + mono_memory_barrier (); \ + __typeof__ (INTRIN) atomic_ret__ = (INTRIN); \ + mono_memory_barrier (); \ + atomic_ret__; \ + }) + +#define gcc_sync_val_compare_and_swap(a, b, c) WRAP_ATOMIC_INTRINSIC (__sync_val_compare_and_swap (a, b, c)) +#define gcc_sync_add_and_fetch(a, b) WRAP_ATOMIC_INTRINSIC (__sync_add_and_fetch (a, b)) +#define gcc_sync_sub_and_fetch(a, b) WRAP_ATOMIC_INTRINSIC (__sync_sub_and_fetch (a, b)) +#define gcc_sync_fetch_and_add(a, b) WRAP_ATOMIC_INTRINSIC (__sync_fetch_and_add (a, b)) +#else +#define gcc_sync_val_compare_and_swap(a, b, c) __sync_val_compare_and_swap (a, b, c) +#define gcc_sync_add_and_fetch(a, b) __sync_add_and_fetch (a, b) +#define gcc_sync_sub_and_fetch(a, b) __sync_sub_and_fetch (a, b) +#define gcc_sync_fetch_and_add(a, b) __sync_fetch_and_add (a, b) +#endif + static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp) { - return __sync_val_compare_and_swap (dest, comp, exch); + return gcc_sync_val_compare_and_swap (dest, comp, exch); } static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp) { - return __sync_val_compare_and_swap (dest, comp, exch); + return gcc_sync_val_compare_and_swap (dest, comp, exch); } static inline gint32 InterlockedAdd(volatile gint32 *dest, gint32 add) { - return __sync_add_and_fetch (dest, add); + return gcc_sync_add_and_fetch (dest, add); } static inline gint32 InterlockedIncrement(volatile gint32 *val) { - return __sync_add_and_fetch (val, 1); + return gcc_sync_add_and_fetch (val, 1); } static inline gint32 InterlockedDecrement(volatile gint32 *val) { - return __sync_sub_and_fetch (val, 1); + return gcc_sync_sub_and_fetch (val, 1); } static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val) @@ -211,7 +244,7 @@ static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val) gint32 old_val; do { old_val = *val; - } while (__sync_val_compare_and_swap (val, old_val, new_val) != old_val); + } while (gcc_sync_val_compare_and_swap (val, old_val, new_val) != old_val); return old_val; } @@ -221,30 +254,30 @@ static inline gpointer InterlockedExchangePointer(volatile gpointer *val, gpointer old_val; do { old_val = *val; - } while (__sync_val_compare_and_swap (val, old_val, new_val) != old_val); + } while (gcc_sync_val_compare_and_swap (val, old_val, new_val) != old_val); return old_val; } static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add) { - return __sync_fetch_and_add (val, add); + return gcc_sync_fetch_and_add (val, add); } static inline gint8 InterlockedRead8(volatile gint8 *src) { /* Kind of a hack, but GCC doesn't give us anything better, and it's * certainly not as bad as using a CAS loop. */ - return __sync_fetch_and_add (src, 0); + return gcc_sync_fetch_and_add (src, 0); } static inline gint16 InterlockedRead16(volatile gint16 *src) { - return __sync_fetch_and_add (src, 0); + return gcc_sync_fetch_and_add (src, 0); } static inline gint32 InterlockedRead(volatile gint32 *src) { - return __sync_fetch_and_add (src, 0); + return gcc_sync_fetch_and_add (src, 0); } static inline void InterlockedWrite8(volatile gint8 *dst, gint8 val) @@ -253,7 +286,7 @@ static inline void InterlockedWrite8(volatile gint8 *dst, gint8 val) gint8 old_val; do { old_val = *dst; - } while (__sync_val_compare_and_swap (dst, old_val, val) != old_val); + } while (gcc_sync_val_compare_and_swap (dst, old_val, val) != old_val); } static inline void InterlockedWrite16(volatile gint16 *dst, gint16 val) @@ -261,7 +294,7 @@ static inline void InterlockedWrite16(volatile gint16 *dst, gint16 val) gint16 old_val; do { old_val = *dst; - } while (__sync_val_compare_and_swap (dst, old_val, val) != old_val); + } while (gcc_sync_val_compare_and_swap (dst, old_val, val) != old_val); } static inline void InterlockedWrite(volatile gint32 *dst, gint32 val) @@ -270,7 +303,7 @@ static inline void InterlockedWrite(volatile gint32 *dst, gint32 val) gint32 old_val; do { old_val = *dst; - } while (__sync_val_compare_and_swap (dst, old_val, val) != old_val); + } while (gcc_sync_val_compare_and_swap (dst, old_val, val) != old_val); } #if defined (TARGET_OSX) || defined (__arm__) || (defined (__mips__) && !defined (__mips64)) || (defined (__powerpc__) && !defined (__powerpc64__)) || (defined (__sparc__) && !defined (__arch64__)) @@ -281,33 +314,33 @@ static inline void InterlockedWrite(volatile gint32 *dst, gint32 val) static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) { - return __sync_val_compare_and_swap (dest, comp, exch); + return gcc_sync_val_compare_and_swap (dest, comp, exch); } static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add) { - return __sync_add_and_fetch (dest, add); + return gcc_sync_add_and_fetch (dest, add); } static inline gint64 InterlockedIncrement64(volatile gint64 *val) { - return __sync_add_and_fetch (val, 1); + return gcc_sync_add_and_fetch (val, 1); } static inline gint64 InterlockedDecrement64(volatile gint64 *val) { - return __sync_sub_and_fetch (val, 1); + return gcc_sync_sub_and_fetch (val, 1); } static inline gint64 InterlockedExchangeAdd64(volatile gint64 *val, gint64 add) { - return __sync_fetch_and_add (val, add); + return gcc_sync_fetch_and_add (val, add); } static inline gint64 InterlockedRead64(volatile gint64 *src) { /* Kind of a hack, but GCC doesn't give us anything better. */ - return __sync_fetch_and_add (src, 0); + return gcc_sync_fetch_and_add (src, 0); } #else @@ -393,122 +426,6 @@ static inline void InterlockedWrite64(volatile gint64 *dst, gint64 val) InterlockedExchange64 (dst, val); } -#elif defined(__ia64__) - -#ifdef __INTEL_COMPILER -#include -#endif - -static inline gint32 InterlockedCompareExchange(gint32 volatile *dest, - gint32 exch, gint32 comp) -{ - gint32 old; - guint64 real_comp; - -#ifdef __INTEL_COMPILER - old = _InterlockedCompareExchange (dest, exch, comp); -#else - /* cmpxchg4 zero extends the value read from memory */ - real_comp = (guint64)(guint32)comp; - asm volatile ("mov ar.ccv = %2 ;;\n\t" - "cmpxchg4.acq %0 = [%1], %3, ar.ccv\n\t" - : "=r" (old) : "r" (dest), "r" (real_comp), "r" (exch)); -#endif - - return(old); -} - -static inline gpointer InterlockedCompareExchangePointer(gpointer volatile *dest, - gpointer exch, gpointer comp) -{ - gpointer old; - -#ifdef __INTEL_COMPILER - old = _InterlockedCompareExchangePointer (dest, exch, comp); -#else - asm volatile ("mov ar.ccv = %2 ;;\n\t" - "cmpxchg8.acq %0 = [%1], %3, ar.ccv\n\t" - : "=r" (old) : "r" (dest), "r" (comp), "r" (exch)); -#endif - - return(old); -} - -static inline gint32 InterlockedIncrement(gint32 volatile *val) -{ -#ifdef __INTEL_COMPILER - return _InterlockedIncrement (val); -#else - gint32 old; - - do { - old = *val; - } while (InterlockedCompareExchange (val, old + 1, old) != old); - - return old + 1; -#endif -} - -static inline gint32 InterlockedDecrement(gint32 volatile *val) -{ -#ifdef __INTEL_COMPILER - return _InterlockedDecrement (val); -#else - gint32 old; - - do { - old = *val; - } while (InterlockedCompareExchange (val, old - 1, old) != old); - - return old - 1; -#endif -} - -static inline gint32 InterlockedExchange(gint32 volatile *dest, gint32 new_val) -{ -#ifdef __INTEL_COMPILER - return _InterlockedExchange (dest, new_val); -#else - gint32 res; - - do { - res = *dest; - } while (InterlockedCompareExchange (dest, new_val, res) != res); - - return res; -#endif -} - -static inline gpointer InterlockedExchangePointer(gpointer volatile *dest, gpointer new_val) -{ -#ifdef __INTEL_COMPILER - return (gpointer)_InterlockedExchange64 ((gint64*)dest, (gint64)new_val); -#else - gpointer res; - - do { - res = *dest; - } while (InterlockedCompareExchangePointer (dest, new_val, res) != res); - - return res; -#endif -} - -static inline gint32 InterlockedExchangeAdd(gint32 volatile *val, gint32 add) -{ - gint32 old; - -#ifdef __INTEL_COMPILER - old = _InterlockedExchangeAdd (val, add); -#else - do { - old = *val; - } while (InterlockedCompareExchange (val, old + add, old) != old); - - return old; -#endif -} - #else #define WAPI_NO_ATOMIC_ASM diff --git a/mono/utils/hazard-pointer.c b/mono/utils/hazard-pointer.c index efe6b649b3..cddcd1c63b 100644 --- a/mono/utils/hazard-pointer.c +++ b/mono/utils/hazard-pointer.c @@ -29,7 +29,6 @@ typedef struct { gpointer p; MonoHazardousFreeFunc free_func; - HazardFreeLocking locking; } DelayedFreeItem; /* The hazard table */ @@ -191,7 +190,7 @@ mono_hazard_pointer_get (void) mono_jit_info_table_add(), which doesn't have to care about hazards because it holds the respective domain lock. */ gpointer -get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index) +mono_get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index) { gpointer p; @@ -287,26 +286,6 @@ mono_hazard_pointer_restore_for_signal_handler (int small_id) overflow_busy [small_id] = 0; } -static gboolean -try_free_delayed_free_item (HazardFreeContext context) -{ - DelayedFreeItem item; - gboolean popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item); - - if (!popped) - return FALSE; - - if ((context == HAZARD_FREE_ASYNC_CTX && item.locking == HAZARD_FREE_MAY_LOCK) || - (is_pointer_hazardous (item.p))) { - mono_lock_free_array_queue_push (&delayed_free_queue, &item); - return FALSE; - } - - item.free_func (item.p); - - return TRUE; -} - /** * mono_thread_hazardous_try_free: * @p: the pointer to free @@ -348,7 +327,7 @@ mono_thread_hazardous_try_free (gpointer p, MonoHazardousFreeFunc free_func) void mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func) { - DelayedFreeItem item = { p, free_func, HAZARD_FREE_MAY_LOCK }; + DelayedFreeItem item = { p, free_func }; InterlockedIncrement (&hazardous_pointer_count); @@ -366,19 +345,48 @@ mono_hazard_pointer_install_free_queue_size_callback (MonoHazardFreeQueueSizeCal queue_size_cb = cb; } +static void +try_free_delayed_free_items (guint32 limit) +{ + GArray *hazardous = NULL; + DelayedFreeItem item; + guint32 freed = 0; + + // Free all the items we can and re-add the ones we can't to the queue. + while (mono_lock_free_array_queue_pop (&delayed_free_queue, &item)) { + if (is_pointer_hazardous (item.p)) { + if (!hazardous) + hazardous = g_array_sized_new (FALSE, FALSE, sizeof (DelayedFreeItem), delayed_free_queue.num_used_entries); + + g_array_append_val (hazardous, item); + continue; + } + + item.free_func (item.p); + freed++; + + if (limit && freed == limit) + break; + } + + if (hazardous) { + for (gint i = 0; i < hazardous->len; i++) + mono_lock_free_array_queue_push (&delayed_free_queue, &g_array_index (hazardous, DelayedFreeItem, i)); + + g_array_free (hazardous, TRUE); + } +} + void mono_thread_hazardous_try_free_all (void) { - while (try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX)) - ; + try_free_delayed_free_items (0); } void mono_thread_hazardous_try_free_some (void) { - int i; - for (i = 0; i < 10; ++i) - try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX); + try_free_delayed_free_items (10); } void diff --git a/mono/utils/hazard-pointer.h b/mono/utils/hazard-pointer.h index 0102c103f7..558c0ad0af 100644 --- a/mono/utils/hazard-pointer.h +++ b/mono/utils/hazard-pointer.h @@ -20,23 +20,13 @@ typedef struct { typedef void (*MonoHazardousFreeFunc) (gpointer p); -typedef enum { - HAZARD_FREE_MAY_LOCK, - HAZARD_FREE_NO_LOCK, -} HazardFreeLocking; - -typedef enum { - HAZARD_FREE_SAFE_CTX, - HAZARD_FREE_ASYNC_CTX, -} HazardFreeContext; - MONO_API gboolean mono_thread_hazardous_try_free (gpointer p, MonoHazardousFreeFunc free_func); -void mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func); +MONO_API void mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func); -void mono_thread_hazardous_try_free_all (void); +MONO_API void mono_thread_hazardous_try_free_all (void); void mono_thread_hazardous_try_free_some (void); -MonoThreadHazardPointers* mono_hazard_pointer_get (void); -gpointer get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index); +MONO_API MonoThreadHazardPointers* mono_hazard_pointer_get (void); +gpointer mono_get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index); #define mono_hazard_pointer_set(hp,i,v) \ do { g_assert ((i) >= 0 && (i) < HAZARD_POINTER_COUNT); \ diff --git a/mono/utils/lock-free-alloc.c b/mono/utils/lock-free-alloc.c index d103ef6aa3..d5da389634 100644 --- a/mono/utils/lock-free-alloc.c +++ b/mono/utils/lock-free-alloc.c @@ -170,7 +170,7 @@ desc_alloc (void) for (;;) { gboolean success; - desc = (Descriptor *) get_hazardous_pointer ((gpointer * volatile)&desc_avail, hp, 1); + desc = (Descriptor *) mono_get_hazardous_pointer ((gpointer * volatile)&desc_avail, hp, 1); if (desc) { Descriptor *next = desc->next; success = (InterlockedCompareExchangePointer ((gpointer * volatile)&desc_avail, next, desc) == desc); diff --git a/mono/utils/lock-free-queue.c b/mono/utils/lock-free-queue.c index 2e06b63f52..3abb841047 100644 --- a/mono/utils/lock-free-queue.c +++ b/mono/utils/lock-free-queue.c @@ -133,7 +133,7 @@ mono_lock_free_queue_enqueue (MonoLockFreeQueue *q, MonoLockFreeQueueNode *node) for (;;) { MonoLockFreeQueueNode *next; - tail = (MonoLockFreeQueueNode *) get_hazardous_pointer ((gpointer volatile*)&q->tail, hp, 0); + tail = (MonoLockFreeQueueNode *) mono_get_hazardous_pointer ((gpointer volatile*)&q->tail, hp, 0); mono_memory_read_barrier (); /* * We never dereference next so we don't need a @@ -243,7 +243,7 @@ mono_lock_free_queue_dequeue (MonoLockFreeQueue *q) for (;;) { MonoLockFreeQueueNode *tail, *next; - head = (MonoLockFreeQueueNode *) get_hazardous_pointer ((gpointer volatile*)&q->head, hp, 0); + head = (MonoLockFreeQueueNode *) mono_get_hazardous_pointer ((gpointer volatile*)&q->head, hp, 0); tail = (MonoLockFreeQueueNode*)q->tail; mono_memory_read_barrier (); next = head->next; diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index 2b3b86e2ef..d03ba8051a 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -303,5 +303,9 @@ typedef SSIZE_T ssize_t; #define MONO_COLD #endif +#if defined (__GNUC__) && defined (__GNUC_MINOR__) && defined (__GNUC_PATCHLEVEL__) +#define MONO_GNUC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + #endif /* __UTILS_MONO_COMPILER_H__*/ diff --git a/mono/utils/mono-conc-hashtable.c b/mono/utils/mono-conc-hashtable.c index b5b3539d11..9b92493191 100644 --- a/mono/utils/mono-conc-hashtable.c +++ b/mono/utils/mono-conc-hashtable.c @@ -164,7 +164,7 @@ mono_conc_hashtable_lookup (MonoConcurrentHashTable *hash_table, gpointer key) hp = mono_hazard_pointer_get (); retry: - table = (conc_table *)get_hazardous_pointer ((gpointer volatile*)&hash_table->table, hp, 0); + table = (conc_table *)mono_get_hazardous_pointer ((gpointer volatile*)&hash_table->table, hp, 0); table_mask = table->table_size - 1; kvs = table->kvs; i = hash & table_mask; diff --git a/mono/utils/mono-hwcap-arm.c b/mono/utils/mono-hwcap-arm.c index 758c3dc6fc..e51387776b 100644 --- a/mono/utils/mono-hwcap-arm.c +++ b/mono/utils/mono-hwcap-arm.c @@ -19,7 +19,7 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-arm.h" +#include "mono/utils/mono-hwcap.h" #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID) #include @@ -34,15 +34,6 @@ #include #endif -gboolean mono_hwcap_arm_is_v5 = FALSE; -gboolean mono_hwcap_arm_is_v6 = FALSE; -gboolean mono_hwcap_arm_is_v7 = FALSE; -gboolean mono_hwcap_arm_has_vfp = FALSE; -gboolean mono_hwcap_arm_has_vfp3 = FALSE; -gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE; -gboolean mono_hwcap_arm_has_thumb = FALSE; -gboolean mono_hwcap_arm_has_thumb2 = FALSE; - void mono_hwcap_arch_init (void) { @@ -202,16 +193,3 @@ mono_hwcap_arch_init (void) } #endif } - -void -mono_hwcap_print(FILE *f) -{ - g_fprintf (f, "mono_hwcap_arm_is_v5 = %i\n", mono_hwcap_arm_is_v5); - g_fprintf (f, "mono_hwcap_arm_is_v6 = %i\n", mono_hwcap_arm_is_v6); - g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7); - g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp); - g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3); - g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16); - g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb); - g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2); -} diff --git a/mono/utils/mono-hwcap-arm.h b/mono/utils/mono-hwcap-arm.h deleted file mode 100644 index 29adf7bb79..0000000000 --- a/mono/utils/mono-hwcap-arm.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_ARM_H__ -#define __MONO_UTILS_HWCAP_ARM_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_arm_is_v5; -extern gboolean mono_hwcap_arm_is_v6; -extern gboolean mono_hwcap_arm_is_v7; -extern gboolean mono_hwcap_arm_has_vfp; -extern gboolean mono_hwcap_arm_has_vfp3; -extern gboolean mono_hwcap_arm_has_vfp3_d16; -extern gboolean mono_hwcap_arm_has_thumb; -extern gboolean mono_hwcap_arm_has_thumb2; - -#endif /* __MONO_UTILS_HWCAP_ARM_H__ */ diff --git a/mono/utils/mono-hwcap-arm64.c b/mono/utils/mono-hwcap-arm64.c index 5491cff96c..f541ea3df2 100644 --- a/mono/utils/mono-hwcap-arm64.c +++ b/mono/utils/mono-hwcap-arm64.c @@ -1,25 +1,13 @@ /* - * mono-hwcap-arm64.c: ARM hardware feature detection + * mono-hwcap-arm64.c: ARM64 hardware feature detection * * Copyright 2013 Xamarin Inc * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-arm64.h" +#include "mono/utils/mono-hwcap.h" -#if defined(MONO_CROSS_COMPILE) void mono_hwcap_arch_init (void) { } -#else -void -mono_hwcap_arch_init (void) -{ -} -#endif - -void -mono_hwcap_print(FILE *f) -{ -} diff --git a/mono/utils/mono-hwcap-arm64.h b/mono/utils/mono-hwcap-arm64.h deleted file mode 100644 index 2d4120957c..0000000000 --- a/mono/utils/mono-hwcap-arm64.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_ARM64_H__ -#define __MONO_UTILS_HWCAP_ARM64_H__ - -#include "mono/utils/mono-hwcap.h" - -#endif diff --git a/mono/utils/mono-hwcap-cross.c b/mono/utils/mono-hwcap-cross.c new file mode 100644 index 0000000000..4311a99a18 --- /dev/null +++ b/mono/utils/mono-hwcap-cross.c @@ -0,0 +1,16 @@ +/* + * mono-hwcap-cross.c: No-op hardware feature detection + * + * Author: + * Alex Rønne Petersen (alexrp@xamarin.com) + * + * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include "mono/utils/mono-hwcap.h" + +void +mono_hwcap_arch_init (void) +{ +} diff --git a/mono/utils/mono-hwcap-ia64.c b/mono/utils/mono-hwcap-ia64.c index b597986220..dd1edbd8d4 100644 --- a/mono/utils/mono-hwcap-ia64.c +++ b/mono/utils/mono-hwcap-ia64.c @@ -19,15 +19,9 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-ia64.h" +#include "mono/utils/mono-hwcap.h" void mono_hwcap_arch_init (void) -{ - /* Nothing needed here yet. */ -} - -void -mono_hwcap_print (FILE *f) { } diff --git a/mono/utils/mono-hwcap-ia64.h b/mono/utils/mono-hwcap-ia64.h deleted file mode 100644 index 15b64a83c6..0000000000 --- a/mono/utils/mono-hwcap-ia64.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_IA64_H__ -#define __MONO_UTILS_HWCAP_IA64_H__ - -#include "mono/utils/mono-hwcap.h" - -/* Nothing needed here yet. */ - -#endif /* __MONO_UTILS_HWCAP_IA64_H__ */ diff --git a/mono/utils/mono-hwcap-mips.c b/mono/utils/mono-hwcap-mips.c index 6d809a79ac..119f930a68 100644 --- a/mono/utils/mono-hwcap-mips.c +++ b/mono/utils/mono-hwcap-mips.c @@ -19,15 +19,9 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-mips.h" +#include "mono/utils/mono-hwcap.h" void mono_hwcap_arch_init (void) -{ - /* Nothing needed here yet. */ -} - -void -mono_hwcap_print (FILE *f) { } diff --git a/mono/utils/mono-hwcap-mips.h b/mono/utils/mono-hwcap-mips.h deleted file mode 100644 index dd0622ab1a..0000000000 --- a/mono/utils/mono-hwcap-mips.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_MIPS_H__ -#define __MONO_UTILS_HWCAP_MIPS_H__ - -#include "mono/utils/mono-hwcap.h" - -/* Nothing needed here yet. */ - -#endif /* __MONO_UTILS_HWCAP_MIPS_H__ */ diff --git a/mono/utils/mono-hwcap-ppc.c b/mono/utils/mono-hwcap-ppc.c index 174cc620a2..af36c4d547 100644 --- a/mono/utils/mono-hwcap-ppc.c +++ b/mono/utils/mono-hwcap-ppc.c @@ -19,19 +19,13 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-ppc.h" +#include "mono/utils/mono-hwcap.h" #if defined(__linux__) && defined(HAVE_SYS_AUXV_H) #include #include #endif -gboolean mono_hwcap_ppc_has_icache_snoop = FALSE; -gboolean mono_hwcap_ppc_is_isa_2x = FALSE; -gboolean mono_hwcap_ppc_is_isa_64 = FALSE; -gboolean mono_hwcap_ppc_has_move_fpr_gpr = FALSE; -gboolean mono_hwcap_ppc_has_multiple_ls_units = FALSE; - void mono_hwcap_arch_init (void) { @@ -66,13 +60,3 @@ mono_hwcap_arch_init (void) } #endif } - -void -mono_hwcap_print (FILE* f) -{ - g_fprintf (f, "mono_hwcap_ppc_has_icache_snoop = %i\n", mono_hwcap_ppc_has_icache_snoop); - g_fprintf (f, "mono_hwcap_ppc_is_isa_2x = %i\n", mono_hwcap_ppc_is_isa_2x); - g_fprintf (f, "mono_hwcap_ppc_is_isa_64 = %i\n", mono_hwcap_ppc_is_isa_64); - g_fprintf (f, "mono_hwcap_ppc_has_move_fpr_gpr = %i\n", mono_hwcap_ppc_has_move_fpr_gpr); - g_fprintf (f, "mono_hwcap_ppc_has_multiple_ls_units = %i\n", mono_hwcap_ppc_has_multiple_ls_units); -} diff --git a/mono/utils/mono-hwcap-ppc.h b/mono/utils/mono-hwcap-ppc.h deleted file mode 100644 index 0ae2578e62..0000000000 --- a/mono/utils/mono-hwcap-ppc.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_PPC_H__ -#define __MONO_UTILS_HWCAP_PPC_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_ppc_has_icache_snoop; -extern gboolean mono_hwcap_ppc_is_isa_2x; -extern gboolean mono_hwcap_ppc_is_isa_64; -extern gboolean mono_hwcap_ppc_has_move_fpr_gpr; -extern gboolean mono_hwcap_ppc_has_multiple_ls_units; - -#endif /* __MONO_UTILS_HWCAP_PPC_H__ */ diff --git a/mono/utils/mono-hwcap-s390x.c b/mono/utils/mono-hwcap-s390x.c index 19a7fba110..c578a620d9 100644 --- a/mono/utils/mono-hwcap-s390x.c +++ b/mono/utils/mono-hwcap-s390x.c @@ -19,22 +19,117 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-s390x.h" +#include "mono/utils/mono-hwcap.h" + #include -facilityList_t facs; +typedef struct { + uint8_t n3:1; // 000 - N3 instructions + uint8_t zi:1; // 001 - z/Arch installed + uint8_t za:1; // 002 - z/Arch active + uint8_t date:1; // 003 - DAT-enhancement + uint8_t idtes:1; // 004 - IDTE-segment tables + uint8_t idter:1; // 005 - IDTE-region tables + uint8_t asnlx:1; // 006 - ASN-LX reuse + uint8_t stfle:1; // 007 - STFLE + uint8_t edat1:1; // 008 - EDAT 1 + uint8_t srs:1; // 009 - Sense-Running-Status + uint8_t csske:1; // 010 - Conditional SSKE + uint8_t ctf:1; // 011 - Configuration-topology + uint8_t ibm01:1; // 012 - Assigned to IBM + uint8_t ipter:1; // 013 - IPTE-range + uint8_t nqks:1; // 014 - Nonquiescing key-setting + uint8_t ibm02:1; // 015 - Assigned to IBM + uint8_t etf2:1; // 016 - Extended translation 2 + uint8_t msa:1; // 017 - Message security assist 1 + uint8_t ld:1; // 018 - Long displacement + uint8_t ldh:1; // 019 - Long displacement high perf + uint8_t mas:1; // 020 - HFP multiply-add-subtract + uint8_t eif:1; // 021 - Extended immediate + uint8_t etf3:1; // 022 - Extended translation 3 + uint8_t hux:1; // 023 - HFP unnormalized extension + uint8_t etf2e:1; // 024 - Extended translation enhanced 2 + uint8_t stckf:1; // 025 - Store clock fast + uint8_t pe:1; // 026 - Parsing enhancement + uint8_t mvcos:1; // 027 - Move with optional specs + uint8_t tods:1; // 028 - TOD steering + uint8_t x000:1; // 029 - Undefined + uint8_t etf3e:1; // 030 - ETF3 enhancement + uint8_t ecput:1; // 031 - Extract CPU time + uint8_t csst:1; // 032 - Compare swap and store + uint8_t csst2:1; // 033 - Compare swap and store 2 + uint8_t gie:1; // 034 - General instructions extension + uint8_t ee:1; // 035 - Execute extensions + uint8_t em:1; // 036 - Enhanced monitor + uint8_t fpe:1; // 037 - Floating point extension + uint8_t x001:1; // 038 - Undefined + uint8_t ibm03:1; // 039 - Assigned to IBM + uint8_t spp:1; // 040 - Set program parameters + uint8_t fpse:1; // 041 - FP support enhancement + uint8_t dfp:1; // 042 - DFP + uint8_t dfph:1; // 043 - DFP high performance + uint8_t pfpo:1; // 044 - PFPO instruction + uint8_t multi:1; // 045 - Multiple inc load/store on CC 1 + uint8_t ibm04:1; // 046 - Assigned to IBM + uint8_t cmpsce:1; // 047 - CMPSC enhancement + uint8_t dfpzc:1; // 048 - DFP zoned conversion + uint8_t misc:1; // 049 - Multiple inc load and trap + uint8_t ctx:1; // 050 - Constrained transactional-execution + uint8_t ltlb:1; // 051 - Local TLB clearing + uint8_t ia:1; // 052 - Interlocked access + uint8_t lsoc2:1; // 053 - Load/store on CC 2 + uint8_t x002:1; // 054 - Undefined + uint8_t ibm05:1; // 055 - Assigned to IBM + uint8_t x003:1; // 056 - Undefined + uint8_t msa5:1; // 057 - Message security assist 5 + uint8_t x004:1; // 058 - Undefined + uint8_t x005:1; // 059 - Undefined + uint8_t x006:1; // 060 - Undefined + uint8_t x007:1; // 061 - Undefined + uint8_t ibm06:1; // 062 - Assigned to IBM + uint8_t x008:1; // 063 - Undefined + uint8_t x009:1; // 064 - Undefined + uint8_t ibm07:1; // 065 - Assigned to IBM + uint8_t rrbm:1; // 066 - Reset reference bits multiple + uint8_t cmc:1; // 067 - CPU measurement counter + uint8_t cms:1; // 068 - CPU Measurement sampling + uint8_t ibm08:1; // 069 - Assigned to IBM + uint8_t ibm09:1; // 070 - Assigned to IBM + uint8_t ibm10:1; // 071 - Assigned to IBM + uint8_t ibm11:1; // 072 - Assigned to IBM + uint8_t txe:1; // 073 - Transactional execution + uint8_t sthy:1; // 074 - Store hypervisor information + uint8_t aefsi:1; // 075 - Access exception fetch/store indication + uint8_t msa3:1; // 076 - Message security assist 3 + uint8_t msa4:1; // 077 - Message security assist 4 + uint8_t edat2:1; // 078 - Enhanced DAT 2 + uint8_t x010:1; // 079 - Undefined + uint8_t dfppc:1; // 080 - DFP packed conversion + uint8_t x011:7; // 081-87 - Undefined + uint8_t x012[5]; // 088-127 - Undefined + uint8_t ibm12:1; // 128 - Assigned to IBM + uint8_t vec:1; // 129 - Vector facility + uint8_t x013:6; // 130-135 - Undefined + uint8_t x014:6; // 136-141 - Undefined + uint8_t sccm:1; // 142 - Store CPU counter multiple + uint8_t ibm13:1; // 143 - Assigned to IBM + uint8_t x015[14]; // 144-256 Undefined +} __attribute__ ((packed)) __attribute__ ((aligned(8))) facilityList_t; void mono_hwcap_arch_init (void) { - int lFacs = sizeof(facs) / 8; + facilityList_t facs; + int lFacs = sizeof (facs) / 8; - __asm__ (" lgfr 0,%1\n" - " .insn s,0xb2b00000,%0\n" - : "=m" (facs) : "r" (lFacs) : "0", "cc"); -} + __asm__ __volatile__ ( + "lgfr\t0,%1\n\t" + ".insn\ts,0xb2b00000,%0\n\t" + : "=m" (facs) + : "r" (lFacs) + : "0", "cc" + ); -void -mono_hwcap_print (FILE *f) -{ + mono_hwcap_s390x_has_fpe = facs.fpe; + mono_hwcap_s390x_has_vec = facs.vec; } diff --git a/mono/utils/mono-hwcap-s390x.h b/mono/utils/mono-hwcap-s390x.h deleted file mode 100644 index 7a4522f8db..0000000000 --- a/mono/utils/mono-hwcap-s390x.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_S390X_H__ -#define __MONO_UTILS_HWCAP_S390X_H__ - -#include "mono/utils/mono-hwcap.h" - -typedef struct __FACLIST__ { - uint8_t n3:1; // 000 - N3 instructions - uint8_t zi:1; // 001 - z/Arch installed - uint8_t za:1; // 002 - z/Arch active - uint8_t date:1; // 003 - DAT-enhancement - uint8_t idtes:1; // 004 - IDTE-segment tables - uint8_t idter:1; // 005 - IDTE-region tables - uint8_t asnlx:1; // 006 - ASN-LX reuse - uint8_t stfle:1; // 007 - STFLE - uint8_t edat1:1; // 008 - EDAT 1 - uint8_t srs:1; // 009 - Sense-Running-Status - uint8_t csske:1; // 010 - Conditional SSKE - uint8_t ctf:1; // 011 - Configuration-topology - uint8_t ibm01:1; // 012 - Assigned to IBM - uint8_t ipter:1; // 013 - IPTE-range - uint8_t nqks:1; // 014 - Nonquiescing key-setting - uint8_t ibm02:1; // 015 - Assigned to IBM - uint8_t etf2:1; // 016 - Extended translation 2 - uint8_t msa:1; // 017 - Message security assist 1 - uint8_t ld:1; // 018 - Long displacement - uint8_t ldh:1; // 019 - Long displacement high perf - uint8_t mas:1; // 020 - HFP multiply-add-subtract - uint8_t eif:1; // 021 - Extended immediate - uint8_t etf3:1; // 022 - Extended translation 3 - uint8_t hux:1; // 023 - HFP unnormalized extension - uint8_t etf2e:1; // 024 - Extended translation enhanced 2 - uint8_t stckf:1; // 025 - Store clock fast - uint8_t pe:1; // 026 - Parsing enhancement - uint8_t mvcos:1; // 027 - Move with optional specs - uint8_t tods:1; // 028 - TOD steering - uint8_t x000:1; // 029 - Undefined - uint8_t etf3e:1; // 030 - ETF3 enhancement - uint8_t ecput:1; // 031 - Extract CPU time - uint8_t csst:1; // 032 - Compare swap and store - uint8_t csst2:1; // 033 - Compare swap and store 2 - uint8_t gie:1; // 034 - General instructions extension - uint8_t ee:1; // 035 - Execute extensions - uint8_t em:1; // 036 - Enhanced monitor - uint8_t fpe:1; // 037 - Floating point extension - uint8_t x001:1; // 038 - Undefined - uint8_t ibm03:1; // 039 - Assigned to IBM - uint8_t spp:1; // 040 - Set program parameters - uint8_t fpse:1; // 041 - FP support enhancement - uint8_t dfp:1; // 042 - DFP - uint8_t dfph:1; // 043 - DFP high performance - uint8_t pfpo:1; // 044 - PFPO instruction - uint8_t multi:1; // 045 - Multiple inc load/store on CC 1 - uint8_t ibm04:1; // 046 - Assigned to IBM - uint8_t cmpsce:1; // 047 - CMPSC enhancement - uint8_t dfpzc:1; // 048 - DFP zoned conversion - uint8_t misc:1; // 049 - Multiple inc load and trap - uint8_t ctx:1; // 050 - Constrained transactional-execution - uint8_t ltlb:1; // 051 - Local TLB clearing - uint8_t ia:1; // 052 - Interlocked access - uint8_t lsoc2:1; // 053 - Load/store on CC 2 - uint8_t x002:1; // 054 - Undefined - uint8_t ibm05:1; // 055 - Assigned to IBM - uint8_t x003:1; // 056 - Undefined - uint8_t msa5:1; // 057 - Message security assist 5 - uint8_t x004:1; // 058 - Undefined - uint8_t x005:1; // 059 - Undefined - uint8_t x006:1; // 060 - Undefined - uint8_t x007:1; // 061 - Undefined - uint8_t ibm06:1; // 062 - Assigned to IBM - uint8_t x008:1; // 063 - Undefined - uint8_t x009:1; // 064 - Undefined - uint8_t ibm07:1; // 065 - Assigned to IBM - uint8_t rrbm:1; // 066 - Reset reference bits multiple - uint8_t cmc:1; // 067 - CPU measurement counter - uint8_t cms:1; // 068 - CPU Measurement sampling - uint8_t ibm08:1; // 069 - Assigned to IBM - uint8_t ibm09:1; // 070 - Assigned to IBM - uint8_t ibm10:1; // 071 - Assigned to IBM - uint8_t ibm11:1; // 072 - Assigned to IBM - uint8_t txe:1; // 073 - Transactional execution - uint8_t sthy:1; // 074 - Store hypervisor information - uint8_t aefsi:1; // 075 - Access exception fetch/store indication - uint8_t msa3:1; // 076 - Message security assist 3 - uint8_t msa4:1; // 077 - Message security assist 4 - uint8_t edat2:1; // 078 - Enhanced DAT 2 - uint8_t x010:1; // 079 - Undefined - uint8_t dfppc:1; // 080 - DFP packed conversion - uint8_t x011:7; // 081-87 - Undefined - uint8_t x012[5]; // 088-127 - Undefined - uint8_t ibm12:1; // 128 - Assigned to IBM - uint8_t vec:1; // 129 - Vector facility - uint8_t x013:6; // 130-135 - Undefined - uint8_t x014:6; // 136-141 - Undefined - uint8_t sccm:1; // 142 - Store CPU counter multiple - uint8_t ibm13:1; // 143 - Assigned to IBM - uint8_t x015[14]; // 144-256 Undefined -} __attribute__ ((packed)) __attribute__ ((aligned(8))) facilityList_t; - -extern facilityList_t facs; - -#endif /* __MONO_UTILS_HWCAP_S390X_H__ */ diff --git a/mono/utils/mono-hwcap-sparc.c b/mono/utils/mono-hwcap-sparc.c index ba84987363..75208bdeff 100644 --- a/mono/utils/mono-hwcap-sparc.c +++ b/mono/utils/mono-hwcap-sparc.c @@ -19,26 +19,22 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-sparc.h" +#include "mono/utils/mono-hwcap.h" #include - #if !defined(__linux__) #include #else #include #endif -gboolean mono_hwcap_sparc_is_v9 = FALSE; - void mono_hwcap_arch_init (void) { char buf [1024]; #if !defined(__linux__) - if (!sysinfo (SI_ISALIST, buf, 1024)) - g_assert_not_reached (); + g_assert (sysinfo (SI_ISALIST, buf, 1024)); #else /* If the page size is 8192, we're on a 64-bit SPARC, which * in turn means a v9 or better. @@ -51,9 +47,3 @@ mono_hwcap_arch_init (void) mono_hwcap_sparc_is_v9 = strstr (buf, "sparcv9"); } - -void -mono_hwcap_print (FILE *f) -{ - g_fprintf (f, "mono_hwcap_sparc_is_v9 = %i\n", mono_hwcap_sparc_is_v9); -} diff --git a/mono/utils/mono-hwcap-sparc.h b/mono/utils/mono-hwcap-sparc.h deleted file mode 100644 index 98bcf8e064..0000000000 --- a/mono/utils/mono-hwcap-sparc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_SPARC_H__ -#define __MONO_UTILS_HWCAP_SPARC_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_sparc_is_v9; - -#endif /* __MONO_UTILS_HWCAP_SPARC_H__ */ diff --git a/mono/utils/mono-hwcap-vars.h b/mono/utils/mono-hwcap-vars.h new file mode 100644 index 0000000000..620a3d43e4 --- /dev/null +++ b/mono/utils/mono-hwcap-vars.h @@ -0,0 +1,56 @@ +#include "config.h" + +#if defined (TARGET_ARM) + +MONO_HWCAP_VAR(arm_is_v5) +MONO_HWCAP_VAR(arm_is_v6) +MONO_HWCAP_VAR(arm_is_v7) +MONO_HWCAP_VAR(arm_has_vfp) +MONO_HWCAP_VAR(arm_has_vfp3) +MONO_HWCAP_VAR(arm_has_vfp3_d16) +MONO_HWCAP_VAR(arm_has_thumb) +MONO_HWCAP_VAR(arm_has_thumb2) + +#elif defined (TARGET_ARM64) + +// Nothing here yet. + +#elif defined (TARGET_IA64) + +// Nothing here yet. + +#elif defined (TARGET_MIPS) + +// Nothing here yet. + +#elif defined (TARGET_POWERPC) || defined (TARGET_POWERPC64) + +MONO_HWCAP_VAR(ppc_has_icache_snoop) +MONO_HWCAP_VAR(ppc_is_isa_2x) +MONO_HWCAP_VAR(ppc_is_isa_64) +MONO_HWCAP_VAR(ppc_has_move_fpr_gpr) +MONO_HWCAP_VAR(ppc_has_multiple_ls_units) + +#elif defined (TARGET_S390X) + +MONO_HWCAP_VAR(s390x_has_fpe) +MONO_HWCAP_VAR(s390x_has_vec) + +#elif defined (TARGET_SPARC) || defined (TARGET_SPARC64) + +MONO_HWCAP_VAR(sparc_is_v9) + +#elif defined (TARGET_X86) || defined (TARGET_AMD64) + +MONO_HWCAP_VAR(x86_is_xen) +MONO_HWCAP_VAR(x86_has_cmov) +MONO_HWCAP_VAR(x86_has_fcmov) +MONO_HWCAP_VAR(x86_has_sse1) +MONO_HWCAP_VAR(x86_has_sse2) +MONO_HWCAP_VAR(x86_has_sse3) +MONO_HWCAP_VAR(x86_has_ssse3) +MONO_HWCAP_VAR(x86_has_sse41) +MONO_HWCAP_VAR(x86_has_sse42) +MONO_HWCAP_VAR(x86_has_sse4a) + +#endif diff --git a/mono/utils/mono-hwcap-x86.c b/mono/utils/mono-hwcap-x86.c index 4a96aa3a08..5d72a4c7e2 100644 --- a/mono/utils/mono-hwcap-x86.c +++ b/mono/utils/mono-hwcap-x86.c @@ -19,27 +19,15 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-x86.h" +#include "mono/utils/mono-hwcap.h" #if defined(HAVE_UNISTD_H) #include #endif - #if defined(_MSC_VER) #include #endif -gboolean mono_hwcap_x86_is_xen = FALSE; -gboolean mono_hwcap_x86_has_cmov = FALSE; -gboolean mono_hwcap_x86_has_fcmov = FALSE; -gboolean mono_hwcap_x86_has_sse1 = FALSE; -gboolean mono_hwcap_x86_has_sse2 = FALSE; -gboolean mono_hwcap_x86_has_sse3 = FALSE; -gboolean mono_hwcap_x86_has_ssse3 = FALSE; -gboolean mono_hwcap_x86_has_sse41 = FALSE; -gboolean mono_hwcap_x86_has_sse42 = FALSE; -gboolean mono_hwcap_x86_has_sse4a = FALSE; - static gboolean cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx) { @@ -162,18 +150,3 @@ mono_hwcap_arch_init (void) mono_hwcap_x86_is_xen = !access ("/proc/xen", F_OK); #endif } - -void -mono_hwcap_print (FILE *f) -{ - g_fprintf (f, "mono_hwcap_x86_is_xen = %i\n", mono_hwcap_x86_is_xen); - g_fprintf (f, "mono_hwcap_x86_has_cmov = %i\n", mono_hwcap_x86_has_cmov); - g_fprintf (f, "mono_hwcap_x86_has_fcmov = %i\n", mono_hwcap_x86_has_fcmov); - g_fprintf (f, "mono_hwcap_x86_has_sse1 = %i\n", mono_hwcap_x86_has_sse1); - g_fprintf (f, "mono_hwcap_x86_has_sse2 = %i\n", mono_hwcap_x86_has_sse2); - g_fprintf (f, "mono_hwcap_x86_has_sse3 = %i\n", mono_hwcap_x86_has_sse3); - g_fprintf (f, "mono_hwcap_x86_has_ssse3 = %i\n", mono_hwcap_x86_has_ssse3); - g_fprintf (f, "mono_hwcap_x86_has_sse41 = %i\n", mono_hwcap_x86_has_sse41); - g_fprintf (f, "mono_hwcap_x86_has_sse42 = %i\n", mono_hwcap_x86_has_sse42); - g_fprintf (f, "mono_hwcap_x86_has_sse4a = %i\n", mono_hwcap_x86_has_sse4a); -} diff --git a/mono/utils/mono-hwcap-x86.h b/mono/utils/mono-hwcap-x86.h deleted file mode 100644 index 5e1f4f7b47..0000000000 --- a/mono/utils/mono-hwcap-x86.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_X86_H__ -#define __MONO_UTILS_HWCAP_X86_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_x86_is_xen; -extern gboolean mono_hwcap_x86_has_cmov; -extern gboolean mono_hwcap_x86_has_fcmov; -extern gboolean mono_hwcap_x86_has_sse1; -extern gboolean mono_hwcap_x86_has_sse2; -extern gboolean mono_hwcap_x86_has_sse3; -extern gboolean mono_hwcap_x86_has_ssse3; -extern gboolean mono_hwcap_x86_has_sse41; -extern gboolean mono_hwcap_x86_has_sse42; -extern gboolean mono_hwcap_x86_has_sse4a; - -#endif /* __MONO_UTILS_HWCAP_X86_H__ */ diff --git a/mono/utils/mono-hwcap.c b/mono/utils/mono-hwcap.c index a3d2b6078b..00fad69019 100644 --- a/mono/utils/mono-hwcap.c +++ b/mono/utils/mono-hwcap.c @@ -24,6 +24,10 @@ #include "mono/utils/mono-hwcap.h" +#define MONO_HWCAP_VAR(NAME) gboolean mono_hwcap_ ## NAME = FALSE; +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + static gboolean hwcap_inited = FALSE; void @@ -35,19 +39,21 @@ mono_hwcap_init (void) if (hwcap_inited) return; -#ifdef MONO_CROSS_COMPILE - /* - * If we're cross-compiling, we want to be as - * conservative as possible so that we produce - * code that's portable. Default to that. - */ - if (!conservative) - conservative = "1"; -#endif - if (!conservative || strncmp (conservative, "1", 1)) mono_hwcap_arch_init (); if (verbose && !strncmp (verbose, "1", 1)) - mono_hwcap_print (stdout); + mono_hwcap_print (); +} + +void +mono_hwcap_print (void) +{ + g_print ("[mono-hwcap] Detected following hardware capabilities:\n\n"); + +#define MONO_HWCAP_VAR(NAME) g_print ("\t" #NAME " = %s\n", mono_hwcap_ ## NAME ? "yes" : "no"); +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + + g_print ("\n"); } diff --git a/mono/utils/mono-hwcap.h b/mono/utils/mono-hwcap.h index af5d665426..1867d3d258 100644 --- a/mono/utils/mono-hwcap.h +++ b/mono/utils/mono-hwcap.h @@ -8,6 +8,10 @@ #include "mono/utils/mono-compiler.h" +#define MONO_HWCAP_VAR(NAME) extern gboolean mono_hwcap_ ## NAME; +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + /* Call this function to perform hardware feature detection. Until * this function has been called, all feature variables will be * FALSE as a default. @@ -17,17 +21,14 @@ * result in an inconsistent state of the variables. Further, * feature variables should not be read *while* this function is * executing. - * - * To get at feature variables, include the appropriate header, - * e.g. mono-hwcap-x86.h for x86(-64). */ void mono_hwcap_init (void); /* Implemented in mono-hwcap-$TARGET.c. Do not call. */ void mono_hwcap_arch_init (void); -/* Print detected features to the given file. */ -void mono_hwcap_print (FILE *f); +/* Print detected features to stdout. */ +void mono_hwcap_print (void); /* Please note: If you're going to use the Linux auxiliary vector * to detect CPU features, don't use any of the constant names in diff --git a/mono/utils/mono-linked-list-set.c b/mono/utils/mono-linked-list-set.c index f076034da2..ea11fcc634 100644 --- a/mono/utils/mono-linked-list-set.c +++ b/mono/utils/mono-linked-list-set.c @@ -25,7 +25,7 @@ mask (gpointer n, uintptr_t bit) } gpointer -get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index) +mono_lls_get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index) { gpointer p; @@ -56,28 +56,21 @@ get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers /* Initialize @list and will use @free_node_func to release memory. If @free_node_func is null the caller is responsible for releasing node memory. -If @free_node_func may lock, @free_node_func_locking must be -HAZARD_FREE_MAY_LOCK; otherwise, HAZARD_FREE_NO_LOCK. It is ignored if -@free_node_func is null. */ void -mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking) +mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *)) { list->head = NULL; list->free_node_func = free_node_func; - list->locking = free_node_func_locking; } /* Search @list for element with key @key. -@context specifies whether the function is being called from a lock-free (i.e. -signal handler or world stopped) context. It is only relevant if a node free -function was given. The nodes next, cur and prev are returned in @hp. Returns true if a node with key @key was found. */ gboolean -mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context) +mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key) { MonoLinkedListSetNode *cur, *next; MonoLinkedListSetNode **prev; @@ -95,12 +88,12 @@ try_again: */ mono_hazard_pointer_set (hp, 2, prev); - cur = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer*)prev, hp, 1); + cur = (MonoLinkedListSetNode *) mono_lls_get_hazardous_pointer_with_mask ((gpointer*)prev, hp, 1); while (1) { if (cur == NULL) return FALSE; - next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer*)&cur->next, hp, 0); + next = (MonoLinkedListSetNode *) mono_lls_get_hazardous_pointer_with_mask ((gpointer*)&cur->next, hp, 0); cur_key = cur->key; /* @@ -137,15 +130,12 @@ try_again: /* Insert @value into @list. -@context specifies whether the function is being called from a lock-free (i.e. -signal handler or world stopped) context. It is only relevant if a node free -function was given. The nodes value, cur and prev are returned in @hp. Return true if @value was inserted by this call. If it returns FALSE, it's the caller resposibility to release memory. */ gboolean -mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context) +mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value) { MonoLinkedListSetNode *cur, **prev; /*We must do a store barrier before inserting @@ -153,7 +143,7 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink mono_memory_barrier (); while (1) { - if (mono_lls_find (list, hp, value->key, context)) + if (mono_lls_find (list, hp, value->key)) return FALSE; cur = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 1); prev = (MonoLinkedListSetNode **) mono_hazard_pointer_get_val (hp, 2); @@ -169,18 +159,15 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink /* Search @list for element with key @key and remove it. -@context specifies whether the function is being called from a lock-free (i.e. -signal handler or world stopped) context. It is only relevant if a node free -function was given. The nodes next, cur and prev are returned in @hp Returns true if @value was removed by this call. */ gboolean -mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context) +mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value) { MonoLinkedListSetNode *cur, **prev, *next; while (1) { - if (!mono_lls_find (list, hp, value->key, context)) + if (!mono_lls_find (list, hp, value->key)) return FALSE; next = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 0); @@ -198,9 +185,9 @@ mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink mono_memory_write_barrier (); mono_hazard_pointer_clear (hp, 1); if (list->free_node_func) - mono_thread_hazardous_try_free (value, list->free_node_func); + mono_thread_hazardous_queue_free (value, list->free_node_func); } else - mono_lls_find (list, hp, value->key, context); + mono_lls_find (list, hp, value->key); return TRUE; } } diff --git a/mono/utils/mono-linked-list-set.h b/mono/utils/mono-linked-list-set.h index 947602f0c3..ee4d77799e 100644 --- a/mono/utils/mono-linked-list-set.h +++ b/mono/utils/mono-linked-list-set.h @@ -24,7 +24,6 @@ struct _MonoLinkedListSetNode { typedef struct { MonoLinkedListSetNode *head; void (*free_node_func)(void *); - HazardFreeLocking locking; } MonoLinkedListSet; @@ -45,20 +44,20 @@ Those are low level operations. prev, cur, next are returned in the hazard point You must manually clean the hazard pointer table after using them. */ -void -mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking); +MONO_API void +mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *)); -gboolean -mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context); +MONO_API gboolean +mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key); -gboolean -mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context); +MONO_API gboolean +mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value); -gboolean -mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context); +MONO_API gboolean +mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value); -gpointer -get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index); +MONO_API gpointer +mono_lls_get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index); static inline gboolean mono_lls_filter_accept_all (gpointer elem) @@ -108,12 +107,12 @@ mono_lls_filter_accept_all (gpointer elem) restart__ = FALSE; \ MonoLinkedListSetNode **prev__ = &list__->head; \ mono_hazard_pointer_set (hp__, 2, prev__); \ - MonoLinkedListSetNode *cur__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) prev__, hp__, 1); \ + MonoLinkedListSetNode *cur__ = (MonoLinkedListSetNode *) mono_lls_get_hazardous_pointer_with_mask ((gpointer *) prev__, hp__, 1); \ while (1) { \ if (!cur__) { \ break; \ } \ - MonoLinkedListSetNode *next__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) &cur__->next, hp__, 0); \ + MonoLinkedListSetNode *next__ = (MonoLinkedListSetNode *) mono_lls_get_hazardous_pointer_with_mask ((gpointer *) &cur__->next, hp__, 0); \ uintptr_t ckey__ = cur__->key; \ mono_memory_read_barrier (); \ if (*prev__ != cur__) { \ diff --git a/mono/utils/mono-membar.h b/mono/utils/mono-membar.h index 60f6164dc4..b59ffff85f 100644 --- a/mono/utils/mono-membar.h +++ b/mono/utils/mono-membar.h @@ -56,21 +56,6 @@ static inline void mono_memory_read_barrier (void) mono_memory_barrier (); } -static inline void mono_memory_write_barrier (void) -{ - mono_memory_barrier (); -} -#elif defined(__ia64__) -static inline void mono_memory_barrier (void) -{ - __asm__ __volatile__ ("mf" : : : "memory"); -} - -static inline void mono_memory_read_barrier (void) -{ - mono_memory_barrier (); -} - static inline void mono_memory_write_barrier (void) { mono_memory_barrier (); diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index bf2f273b68..244df6a887 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -278,7 +278,7 @@ mono_thread_info_lookup (MonoNativeThreadId id) { MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - if (!mono_lls_find (&thread_list, hp, (uintptr_t)id, HAZARD_FREE_ASYNC_CTX)) { + if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) { mono_hazard_pointer_clear_all (hp, -1); return NULL; } @@ -292,7 +292,7 @@ mono_thread_info_insert (MonoThreadInfo *info) { MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX)) { + if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info)) { mono_hazard_pointer_clear_all (hp, -1); return FALSE; } @@ -308,7 +308,7 @@ mono_thread_info_remove (MonoThreadInfo *info) gboolean res; THREADS_DEBUG ("removing info %p\n", info); - res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX); + res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info); mono_hazard_pointer_clear_all (hp, -1); return res; } @@ -675,7 +675,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size) mono_os_sem_init (&global_suspend_semaphore, 1); mono_os_sem_init (&suspend_semaphore, 0); - mono_lls_init (&thread_list, NULL, HAZARD_FREE_NO_LOCK); + mono_lls_init (&thread_list, NULL); mono_thread_smr_init (); mono_threads_init_platform (); mono_threads_init_coop (); diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index da88f34e35..774520f600 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -392,7 +392,7 @@ mono_thread_info_is_async_context (void); void mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize); -gboolean +MONO_API gboolean mono_thread_info_yield (void); gint diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index 84476fbc691fabe4c6629c80c9ef79c5693ed573..0315e42c9106568936f10cec1c896eac933bc6aa 100644 GIT binary patch delta 20 bcmbQIHBW29Q!aK(1p{*{1H;X4xQw^}N}dLH delta 20 bcmbQIHBW29Q!aKx1w#WXW7ExVxQw^}N;U>? diff --git a/po/mcs/de.po.REMOVED.git-id b/po/mcs/de.po.REMOVED.git-id index aad6dd6478..b7e5d7dd73 100644 --- a/po/mcs/de.po.REMOVED.git-id +++ b/po/mcs/de.po.REMOVED.git-id @@ -1 +1 @@ -f70132cae7f2b6b9b69bf023807d00ef257e4adf \ No newline at end of file +31076442ea3698ce3dd1e125cd282082aded321b \ No newline at end of file diff --git a/po/mcs/es.gmo b/po/mcs/es.gmo index adb2b44323c7b038ea15d80f3d1bffb32fc305d6..9dd2548249585c2aaedbd8a7f7e8d0a882f26eaf 100644 GIT binary patch delta 20 bcmX?Ef3kjqo+7)Yf`Pe}f#GIT#VK+CQN9MP delta 20 bcmX?Ef3kjqo+7)Uf}w$xvFT=0#VK+CQC0?~ diff --git a/po/mcs/es.po.REMOVED.git-id b/po/mcs/es.po.REMOVED.git-id index bd85b497b1..35413faa4f 100644 --- a/po/mcs/es.po.REMOVED.git-id +++ b/po/mcs/es.po.REMOVED.git-id @@ -1 +1 @@ -4788ec011a757c59b54897654dca4f00897523b0 \ No newline at end of file +44c1885888fd7975851a38137e1f2359ae94fca4 \ No newline at end of file diff --git a/po/mcs/ja.gmo b/po/mcs/ja.gmo index c5f6dc2008ae1586b317d7730026f9833a7dde16..2736541144ad273b8b93c9e40bf2ec0083b6e555 100644 GIT binary patch delta 22 dcmeyri1Gg-#tj_m?3M}!=2ixVoB7oXv;bic2MGWG delta 22 dcmeyri1Gg-#tj_m?1l=423E$VoB7oXv;bhJ2Lb>9 diff --git a/po/mcs/ja.po.REMOVED.git-id b/po/mcs/ja.po.REMOVED.git-id index 98fef2a286..610546ef07 100644 --- a/po/mcs/ja.po.REMOVED.git-id +++ b/po/mcs/ja.po.REMOVED.git-id @@ -1 +1 @@ -ce4d45ef0c66f99ecea8d48d9b1510e2fdc770aa \ No newline at end of file +dc37607d81f1efd35350e3cc40a041fbfe84ad90 \ No newline at end of file diff --git a/po/mcs/mcs.pot b/po/mcs/mcs.pot index 41a1ee8eec..e6556bac94 100644 --- a/po/mcs/mcs.pot +++ b/po/mcs/mcs.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mono 4.6.0\n" "Report-Msgid-Bugs-To: http://www.mono-project.com/Bugs\n" -"POT-Creation-Date: 2016-09-01 10:35+0000\n" +"POT-Creation-Date: 2016-09-09 07:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index 7409bd372fa77ec6cd43338d2e4d2599c3b745dd..96a19722da26cdeeca36ba55eed0415ee735106f 100644 GIT binary patch delta 22 ecmX@Po8{zgmJL$V*ew+d%&iOzH!DtC(GCD+DhO-< delta 22 ecmX@Po8{zgmJL$V*bNm74Xlh!H!DtC(GCD*!U$ym diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index 70c07c6a20..b50cd445c1 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -b6f991b7638cdd7773870c00d3c5110a47656110 \ No newline at end of file +b3da446b8368a85d94c695fbb8aca0d2fa9f19a1 \ No newline at end of file