ACCEPTANCE_TESTS_PATH=external
+BENCHMARKER_PATH=$(ACCEPTANCE_TESTS_PATH)/benchmarker
ROSLYN_PATH=$(ACCEPTANCE_TESTS_PATH)/roslyn
CORECLR_PATH=$(ACCEPTANCE_TESTS_PATH)/coreclr
MSTESTSUITE_PATH=$(ACCEPTANCE_TESTS_PATH)/ms-test-suite
ILASM = $(RUNTIME) $(CLASS)/ilasm.exe
include versions.mk
+include profiler-stress.mk
include roslyn.mk
include coreclr.mk
include ms-test-suite.mk
-check-full: check-roslyn check-coreclr check-ms-test-suite
+check-full: check-profiler-stress check-roslyn check-coreclr check-ms-test-suite
clean-local: clean-local-coreclr
{
"name": "ms-test-suite",
"url": "git@github.com:xamarin/ms-test-suite.git",
- "rev": "bcd16462b0b427c582c2b4c81846a42d7ccd527f",
+ "rev": "eb7cd709549bffe170653a50805f1593d66ea81e",
"remote-branch": "origin/master",
"branch": "master",
"directory": "ms-test-suite"
+ },
+ {
+ "name": "benchmarker",
+ "url": "git://github.com/xamarin/benchmarker.git",
+ "rev": "97f618cd585af549dd861b7c142656c496f6a89b",
+ "remote-branch": "origin/master",
+ "branch": "master",
+ "directory": "benchmarker"
}
]
--- /dev/null
+SYS_REFS = \
+ System.dll \
+ System.Core.dll \
+ System.Data.dll \
+ System.Runtime.Serialization.dll \
+ System.Xml.dll \
+ System.Xml.Linq.dll
+
+check-profiler-stress:
+ @$(MAKE) validate-benchmarker RESET_VERSIONS=1
+ cd profiler-stress && $(MCS) -target:exe $(addprefix -r:, $(SYS_REFS)) -out:runner.exe @runner.exe.sources
+ cd profiler-stress && $(RUNTIME) runner.exe
--- /dev/null
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using Newtonsoft.Json;
+
+// Shut up CLS compliance warnings from Json.NET.
+[assembly: CLSCompliant (true)]
+
+namespace Mono.Profiling.Tests.Stress {
+
+ // https://github.com/xamarin/benchmarker/blob/master/tools/libdbmodel/Benchmark.cs
+ class Benchmark {
+ public string Name { get; set; }
+ public string TestDirectory { get; set; }
+ public bool OnlyExplicit { get; set; }
+ public string[] CommandLine { get; set; }
+ public string[] ClientCommandLine { get; set; }
+ public string[] AOTAssemblies { get; set; }
+
+ public static Benchmark Load (string file)
+ {
+ return JsonConvert.DeserializeObject<Benchmark> (File.ReadAllText (file));
+ }
+ }
+
+ static class Program {
+
+ static int Main ()
+ {
+ var depDir = Path.Combine ("..", "external", "benchmarker");
+ var benchDir = Path.Combine (depDir, "benchmarks");
+ var testDir = Path.Combine (depDir, "tests");
+
+ var benchmarks = Directory.EnumerateFiles (benchDir, "*.benchmark")
+ .Select (Benchmark.Load)
+ .Where (b => !b.OnlyExplicit && b.ClientCommandLine == null)
+ .OrderBy (b => b.Name)
+ .ToArray ();
+
+ var monoPath = Path.GetFullPath (Path.Combine ("..", "..", "runtime", "mono-wrapper"));
+ var classDir = Path.GetFullPath (Path.Combine ("..", "..", "mcs", "class", "lib", "net_4_x"));
+
+ var rand = new Random ();
+ var cpus = Environment.ProcessorCount;
+
+ var successes = 0;
+ var failures = 0;
+
+ var sw = Stopwatch.StartNew ();
+
+ for (var i = 0; i < benchmarks.Length; i++) {
+ var bench = benchmarks [i];
+
+ var sampleFreq = rand.Next (0, 1001);
+ var sampleMode = rand.Next (0, 2) == 1 ? "real" : "process";
+ var maxSamples = rand.Next (0, cpus * 2000 + 1);
+ var heapShotFreq = rand.Next (0, 11);
+ var maxFrames = rand.Next (0, 33);
+ var allocMode = rand.Next (0, 2) == 1 ? "alloc" : "noalloc";
+
+ var profOptions = $"sample=cycles/{sampleFreq},sampling-{sampleMode},maxsamples={maxSamples},heapshot={heapShotFreq}gc,maxframes={maxFrames},{allocMode},output=/dev/null";
+
+ var info = new ProcessStartInfo {
+ UseShellExecute = false,
+ WorkingDirectory = Path.Combine (testDir, bench.TestDirectory),
+ FileName = monoPath,
+ Arguments = $"--debug --profile=log:{profOptions} " + string.Join (" ", bench.CommandLine),
+ };
+
+ info.EnvironmentVariables.Clear ();
+ info.EnvironmentVariables.Add ("MONO_PATH", classDir);
+
+ var progress = $"({i + 1}/{benchmarks.Length})";
+
+ Console.ForegroundColor = ConsoleColor.Blue;
+ Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] {progress} Running {bench.Name} with profiler options: {profOptions}");
+ Console.ResetColor ();
+
+ var sw2 = Stopwatch.StartNew ();
+
+ using (var proc = Process.Start (info)) {
+ proc.WaitForExit ();
+ sw2.Stop ();
+
+ Console.WriteLine ();
+
+ if (proc.ExitCode != 0)
+ failures++;
+ else
+ successes++;
+
+ Console.ForegroundColor = proc.ExitCode != 0 ? ConsoleColor.Red : ConsoleColor.Green;
+ Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] {progress} {bench.Name} took {sw2.Elapsed.ToString ("G")} and exited with code: {proc.ExitCode}");
+ Console.ResetColor ();
+ }
+ }
+
+ sw.Stop ();
+
+ Console.ForegroundColor = failures != 0 ? ConsoleColor.Red : ConsoleColor.Green;
+ Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] Finished with {successes}/{benchmarks.Length} passing tests");
+ Console.ResetColor ();
+
+ return failures;
+ }
+ }
+}
--- /dev/null
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonObjectId.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/BinaryConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DataSetConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DataTableConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DateTimeConverterBase.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/RegexConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ConstructorHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/VersionConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DateFormatHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DateTimeZoneHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Formatting.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConstructorAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonPosition.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPath.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JRaw.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Required.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/PreserveReferencesHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/IJsonLineInfo.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonArrayAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonContainerAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DefaultValueHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverterAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonObjectAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializerSettings.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonValidatingReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/IJEnumerable.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/MemberSerialization.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ObjectCreationHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonTextReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonPropertyAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonIgnoreAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonTextWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonWriterException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonReaderException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverterCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConvert.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializationException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/Extensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JConstructor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JContainer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JEnumerable.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JObject.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JArray.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JProperty.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JValue.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/Extensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ErrorContext.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonProperty.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/MissingMemberHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/NullValueHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ReferenceLoopHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchema.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/OnErrorAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MethodCall.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringReference.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/TypeNameHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumValue.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumValues.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringBuffer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ListWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MathUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/WriteState.cs
+runner.cs
SUBMODULES_CONFIG_FILE = $(top_srcdir)/acceptance-tests/SUBMODULES.json
include $(top_srcdir)/scripts/submodules/versions.mk
+$(eval $(call ValidateVersionTemplate,benchmarker,BENCHMARKER))
$(eval $(call ValidateVersionTemplate,roslyn,ROSLYN))
$(eval $(call ValidateVersionTemplate,coreclr,CORECLR))
$(eval $(call ValidateVersionTemplate,ms-test-suite,MSTESTSUITE))
# Bump the given submodule to the revision given by the REV make variable
# If COMMIT is 1, commit the change
+bump-benchmarker: __bump-benchmarker
bump-roslyn: __bump-version-roslyn
bump-coreclr: __bump-version-coreclr
bump-ms-test-suite: __bump-version-ms-test-suite
# Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables
# If COMMIT is 1, commit the change
+bump-branch-benchmarker: __bump-branch-benchmarker
bump-branch-roslyn: __bump-branch-roslyn
bump-branch-coreclr: __bump-branch-coreclr
bump-branch-ms-test-suite: __bump-branch-ms-test-suite
# Bump the given submodule to its current GIT version
# If COMMIT is 1, commit the change
+bump-current-benchmarker: __bump-current-benchmarker
bump-current-roslyn: __bump-current-version-roslyn
bump-current-coreclr: __bump-current-version-coreclr
bump-current-ms-test-suite: __bump-current-version-ms-test-suite
+commit-bump-benchmarker:
+ $(MAKE) bump-benchmarker COMMIT=1
+
commit-bump-roslyn:
$(MAKE) bump-roslyn COMMIT=1
commit-bump-ms-test-suite:
$(MAKE) bump-ms-test-suite COMMIT=1
+commit-bump-current-benchmarker:
+ $(MAKE) bump-current-benchmarker COMMIT=1
+
commit-bump-current-roslyn:
$(MAKE) bump-current-roslyn COMMIT=1
LLVM_SYSTEM_LIBS=`$LLVM_CONFIG --system-libs 2>/dev/null | grep -- -`
llvm_jit_supported=yes
llvm_jit_libs="jit mcjit $llvm_codegen"
- if test $llvm_api_version -gt 100; then
- # Based on llvm 3.9, only aot is currently supported
- llvm_jit_libs="orcjit $llvm_codegen"
- elif test "x$host" != "x$target"; then
+ if test "x$host" != "x$target"; then
# No need for jit libs
llvm_jit_supported=no
llvm_jit_libs=""
+ elif test $llvm_api_version -gt 100; then
+ llvm_jit_libs="orcjit $llvm_codegen"
fi
LLVM_LIBS=`$LLVM_CONFIG --libs analysis core bitwriter $llvm_jit_libs`
if test "x$LLVM_LIBS" = "x"; then
<p>The output of the SCC analysis is passed to the
`cross_references()` callback. It is expected to set the
`is_alive` flag on those strongly connected components that it
- wishes to be kept alive. Only bridged objects will be
- reported to the callback, i.e., non-bridged objects are
- removed from the callback graph.
+ wishes to be kept alive. The value of `is_alive` will be
+ ignored on any SCCs which lack bridges.
<p>In monodroid each bridged object has a corresponding Java
mirror object. In the bridge callback it reifies the Mono
<div class="mapi-header">
enum {
- SGEN_BRIDGE_VERSION = 4
+ SGEN_BRIDGE_VERSION = 5
};
typedef enum {
#include <glib.h>
#include <windows.h>
+#ifdef _MSC_VER
+#include <shlobj.h>
+#endif
#include <direct.h>
#include <io.h>
const gchar *
g_get_home_dir (void)
{
- /* FIXME */
- const gchar *drive = g_getenv ("HOMEDRIVE");
- const gchar *path = g_getenv ("HOMEPATH");
gchar *home_dir = NULL;
-
- if (drive && path) {
- home_dir = g_malloc(strlen(drive) + strlen(path) +1);
- if (home_dir) {
- sprintf(home_dir, "%s%s", drive, path);
- }
+
+#ifdef _MSC_VER
+ PWSTR profile_path = NULL;
+ HRESULT hr = SHGetKnownFolderPath (&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &profile_path);
+ if (SUCCEEDED(hr)) {
+ home_dir = u16to8 (profile_path);
+ CoTaskMemFree (profile_path);
+ }
+#endif
+
+ if (!home_dir) {
+ home_dir = (gchar *) g_getenv ("USERPROFILE");
}
- g_free (drive);
- g_free (path);
+ if (!home_dir) {
+ const gchar *drive = g_getenv ("HOMEDRIVE");
+ const gchar *path = g_getenv ("HOMEPATH");
+
+ if (drive && path) {
+ home_dir = g_malloc (strlen (drive) + strlen (path) + 1);
+ if (home_dir) {
+ sprintf (home_dir, "%s%s", drive, path);
+ }
+ }
+ g_free (drive);
+ g_free (path);
+ }
return home_dir;
}
-Subproject commit ea18396c86ab3f8ba5d0fcd9ada9e066bd4f9f92
+Subproject commit f38c0f5d99b6e44fa906d14e1146fa65a3806cd3
/* 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,
al.1 \
cert2spc.1 \
certmgr.1 \
+ cert-sync.1 \
chktrust.1 \
cilc.1 \
crlupdate.1 \
--- /dev/null
+.\"
+.\" cert-sync manual page.
+.\" Copyright 2016 Microsoft Corp
+.\" Author:
+.\" Jo Shields <joshield@microsoft.com>
+.\"
+.TH Mono "cert-sync"
+.SH NAME
+cert-sync \- Mono Certificate Store Sync Tool
+.SH SYNOPSIS
+.PP
+.B cert-sync [--quiet] [--user] filename
+.SH DESCRIPTION
+This tool allows you to populate a Mono certificate store, from a large
+concatenated list of certificates in PEM format (commonly provided on most
+Linux distributions).
+
+Its use is intended to be automated at Mono install time, by distribution
+packagers, to seamlessly provide SSL support to Mono applications without
+further user interaction.
+.SH OPTIONS
+.TP
+.I "--quiet"
+Suppress verbose output
+.TP
+.I "--user"
+Populate the per-user store in the user's home directory, instead of the
+system-wide store.
+.TP
+.I "filename.crt"
+Path to a certificate bundle. The Mono store will have any extra entries
+removed, and new entries added, to reflect the provided file.
+
+.SH EXAMPLES
+.TP
+.B cert-sync /etc/ssl/certs/ca-certificates.crt
+Synchronize the machine store, from the Debian cert store location
+.TP
+.B cert-sync --user /etc/pki/tls/certs/ca-bundle.crt
+Synchronize the user store, from the Red Hat cert store location
+
+.SH AUTHOR
+Written by Jo Shields
+
+.SH COPYRIGHT
+Copyright (C) 2016 Microsoft Corp
+.SH MAILING LISTS
+Visit http://lists.ximian.com/mailman/listinfo/mono-list for details.
+.SH WEB SITE
+Visit http://www.mono-project.com for details
+.SH SEE ALSO
+.BR certmgr(1)
$ mkbundle -o hello --simple hello.exe
.fi
+.PP
+You can configure options to be passed to the Mono runtime directly
+into your executable, for this, use the
+.I --options
+flag. For example, the following disables inlining, by passing the
+"-O=-inline" command line option to the embedded executable:
+.nf
+
+ $ mkbundle -o hello --options -O=-inline --simple hello.exe
+
.PP
The simple version allows for cross-compiling, this requires a Mono
runtime to be installed in the ~/.mono/targets/TARGET/mono to be
assemblies listed on the command line option. This is useful to
distribute a self-contained image.
.TP
+.I "--env KEY=VALUE"
+Use this to hardcode an environment variable at runtime for KEY to be
+mapped to VALUE. This is useful in scenarios where you want to
+enable certain Mono runtime configuration options that are controlled
+by environment variables.
+.TP
.I "--fetch-target target"
Downloads a precompiled runtime for the specified target from the Mono
distribution site.
Places the output on `out'. If the flag -c is specified, this is the
C host program. If not, this contains the resulting executable.
.TP
+.I "--options OPTS"
+Since the resulting executable will be treated as a standalone
+program, you can use this option to pass configuration options to the
+Mono runtime and bake those into the resulting executable. These
+options are specified as
+.I OPTS.
+.Sp
+You can use the above to configure options that you would typically
+pass on the command line to Mono, before the main program is
+executed.
+.Sp
+Additionally, users of your binary can still configure their own
+options by setting the
+.I MONO_ENV_OPTIONS
+environment variable.
+.TP
.I "--target-server SERVER"
By default the mkbundle tool will download from a Mono server the
target runtimes, you can specify a different server to provide
-.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
program behaviour.
The default is to collect a 100 times per second (100 Hz) the
instruction pointer.
-This is equivalent to the value \[lq]cycles/100\[rq] for
-\f[I]TYPE\f[].
+This is equivalent to the value \[lq]cycles/100\[rq].
+A value of zero for \f[I]FREQ\f[] effectively disables sampling.
On some systems, like with recent Linux kernels, it is possible to
cause the sampling to happen for other events provided by the
performance counters of the cpu.
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
\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
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
\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:
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[]
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
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[]
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.
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
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/
.PP
mono(1)
.SH AUTHORS
-Paolo Molaro.
-
+Paolo Molaro, Alex Rønne Petersen
endif
ifdef FIXTURE
+ifdef NUNIT_LITE
+FIXTURE_ARG = -test=MonoTests.$(FIXTURE)
+else
FIXTURE_ARG = -fixture=MonoTests.$(FIXTURE)
endif
+endif
ifdef TESTNAME
+ifdef NUNIT_LITE
+TESTNAME_ARG = -test=MonoTests.$(TESTNAME)
+else
TESTNAME_ARG = -run=MonoTests.$(TESTNAME)
endif
+endif
ifdef ALWAYS_AOT
test-local-aot-compile: $(topdir)/build/deps/nunit-$(PROFILE).stamp
{
public static class RegistryAclExtensions
{
- [MonoTODO]
public static RegistrySecurity GetAccessControl (this RegistryKey key)
{
- throw new NotImplementedException ();
+ if (key == null)
+ throw new ArgumentNullException (nameof (key));
+
+ return key.GetAccessControl ();
}
- [MonoTODO]
public static RegistrySecurity GetAccessControl (this RegistryKey key, AccessControlSections includeSections)
{
- throw new NotImplementedException ();
+ if (key == null)
+ throw new ArgumentNullException (nameof (key));
+
+ return key.GetAccessControl (includeSections);
}
- [MonoTODO]
public static void SetAccessControl (this RegistryKey key, RegistrySecurity registrySecurity)
{
- throw new NotImplementedException ();
+ if (key == null)
+ throw new ArgumentNullException (nameof (key));
+
+ key.SetAccessControl (registrySecurity);
}
}
}
\ No newline at end of file
[MonoTODO]
public static IntPtr GetNativeImageBase (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
[MonoTODO]
public static IntPtr GetNativeIP (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
[MonoTODO]
public static bool HasNativeImage (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
[MonoTODO]
public static bool HasMethod (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
[MonoTODO]
public static bool HasILOffset (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
[MonoTODO]
public static bool HasSource (this StackFrame stackFrame)
{
+ if (stackFrame == null)
+ throw new ArgumentNullException (nameof (stackFrame));
+
throw new NotImplementedException ();
}
}
{
public static class StringNormalizationExtensions
{
- [MonoTODO]
public static bool IsNormalized(this string value)
{
- throw new NotImplementedException ();
+ if (value == null)
+ throw new ArgumentNullException (nameof (value));
+
+ return value.IsNormalized ();
}
- [MonoTODO]
public static bool IsNormalized(this string value, NormalizationForm normalizationForm)
{
- throw new NotImplementedException ();
+ if (value == null)
+ throw new ArgumentNullException (nameof (value));
+
+ return value.IsNormalized (normalizationForm);
}
- [MonoTODO]
public static String Normalize(this string value)
{
- throw new NotImplementedException ();
+ if (value == null)
+ throw new ArgumentNullException (nameof (value));
+
+ return value.Normalize ();
}
- [MonoTODO]
public static String Normalize(this string value, NormalizationForm normalizationForm)
{
- throw new NotImplementedException ();
+ if (value == null)
+ throw new ArgumentNullException (nameof (value));
+
+ return value.Normalize (normalizationForm);
}
}
}
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Security.AccessControl;
+
namespace System.IO
{
- public static partial class FileSystemAclExtensions
+ public static class FileSystemAclExtensions
{
- [MonoTODO]
- public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo)
+ public static DirectorySecurity GetAccessControl(this DirectoryInfo directoryInfo)
{
- throw new NotImplementedException ();
+ if (directoryInfo == null)
+ throw new ArgumentNullException (nameof (directoryInfo));
+
+ return directoryInfo.GetAccessControl ();
}
- [MonoTODO]
- public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.AccessControlSections includeSections)
+ public static DirectorySecurity GetAccessControl(this DirectoryInfo directoryInfo, AccessControlSections includeSections)
{
- throw new NotImplementedException ();
+ if (directoryInfo == null)
+ throw new ArgumentNullException (nameof (directoryInfo));
+
+ return directoryInfo.GetAccessControl (includeSections);
}
- [MonoTODO]
- public static System.Security.AccessControl.FileSecurity GetAccessControl(this System.IO.FileInfo fileInfo)
+ public static FileSecurity GetAccessControl(this FileInfo fileInfo)
{
- throw new NotImplementedException ();
+ if (fileInfo == null)
+ throw new ArgumentNullException (nameof (fileInfo));
+
+ return fileInfo.GetAccessControl ();
}
- [MonoTODO]
- public static System.Security.AccessControl.FileSecurity GetAccessControl(this System.IO.FileInfo fileInfo, System.Security.AccessControl.AccessControlSections includeSections)
+ public static FileSecurity GetAccessControl(this FileInfo fileInfo, AccessControlSections includeSections)
{
- throw new NotImplementedException ();
+ if (fileInfo == null)
+ throw new ArgumentNullException (nameof (fileInfo));
+
+ return fileInfo.GetAccessControl (includeSections);
}
- [MonoTODO]
- public static System.Security.AccessControl.FileSecurity GetAccessControl(this System.IO.FileStream fileStream)
+ public static FileSecurity GetAccessControl(this FileStream fileStream)
{
- throw new NotImplementedException ();
+ if (fileStream == null)
+ throw new ArgumentNullException (nameof (fileStream));
+
+ return fileStream.GetAccessControl ();
}
- [MonoTODO]
- public static void SetAccessControl(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.DirectorySecurity directorySecurity)
+ public static void SetAccessControl(this DirectoryInfo directoryInfo, DirectorySecurity directorySecurity)
{
- throw new NotImplementedException ();
+ if (directoryInfo == null)
+ throw new ArgumentNullException (nameof (directoryInfo));
+
+ directoryInfo.SetAccessControl (directorySecurity);
}
- [MonoTODO]
- public static void SetAccessControl(this System.IO.FileInfo fileInfo, System.Security.AccessControl.FileSecurity fileSecurity)
+ public static void SetAccessControl(this FileInfo fileInfo, FileSecurity fileSecurity)
{
- throw new NotImplementedException ();
+ if (fileInfo == null)
+ throw new ArgumentNullException (nameof (fileInfo));
+
+ fileInfo.SetAccessControl (fileSecurity);
}
- [MonoTODO]
- public static void SetAccessControl(this System.IO.FileStream fileStream, System.Security.AccessControl.FileSecurity fileSecurity)
+ public static void SetAccessControl(this FileStream fileStream, FileSecurity fileSecurity)
{
- throw new NotImplementedException ();
+ if (fileStream == null)
+ throw new ArgumentNullException (nameof (fileStream));
+
+ fileStream.SetAccessControl (fileSecurity);
}
}
}
\ No newline at end of file
state: socket);
}
- public static Task ConnectAsync(this Socket socket, EndPoint remoteEndPoint)
+ public static Task ConnectAsync(this Socket socket, EndPoint remoteEP)
{
return Task.Factory.FromAsync(
(targetEndPoint, callback, state) => ((Socket)state).BeginConnect(targetEndPoint, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
- remoteEndPoint,
+ remoteEP,
state: socket);
}
this Socket socket,
ArraySegment<byte> buffer,
SocketFlags socketFlags,
- EndPoint remoteEndPoint)
+ EndPoint remoteEP)
{
return Task<int>.Factory.FromAsync(
(targetBuffer, flags, endPoint, callback, state) => ((Socket)state).BeginSendTo(
asyncResult => ((Socket)asyncResult.AsyncState).EndSendTo(asyncResult),
buffer,
socketFlags,
- remoteEndPoint,
+ remoteEP,
state: socket);
}
}
+++ /dev/null
-//
-// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-[assembly: AssemblyTitle ("System.Private.CoreLib.InteropServices.dll")]
-[assembly: AssemblyDescription ("System.Private.CoreLib.InteropServices.dll")]
-[assembly: AssemblyDefaultAlias ("System.Private.CoreLib.InteropServices.dll")]
-[assembly: AssemblyCompany ("Xamarin, Inc.")]
-[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
-[assembly: AssemblyCopyright ("Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)")]
-[assembly: AssemblyVersion ("4.0.0.0")]
-[assembly: AssemblyInformationalVersion ("4.0.0.0")]
-[assembly: AssemblyFileVersion ("4.0.0.0")]
-[assembly: AssemblyDelaySign (true)]
-[assembly: AssemblyKeyFile ("../../msfinal.pub")]
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <PropertyGroup>\r
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
- <ProductVersion>9.0.30729</ProductVersion>\r
- <SchemaVersion>2.0</SchemaVersion>\r
- <ProjectGuid>{5D05F5E2-7378-4A35-B1A3-76ABEB4A71C3}</ProjectGuid>\r
- <OutputType>Library</OutputType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <OutputPath>./../../../class/lib/net_4_x/Facades</OutputPath>\r
- <IntermediateOutputPath>obj-Facades</IntermediateOutputPath>\r
- <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>\r
- <NoStdLib>True</NoStdLib>\r
- \r
- <NoConfig>True</NoConfig>\r
- \r
- <AppDesignerFolder>Properties</AppDesignerFolder>\r
- <RootNamespace>\r
- </RootNamespace>\r
- <AssemblyName>System.Private.CoreLib.InteropServices</AssemblyName>\r
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
- <FileAlignment>512</FileAlignment>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <SignAssembly>true</SignAssembly>\r
- <DelaySign>true</DelaySign>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <AssemblyOriginatorKeyFile>../../msfinal.pub</AssemblyOriginatorKeyFile>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
- <DebugSymbols>true</DebugSymbols>\r
- <DebugType>full</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>false</Optimize>\r
- <DefineConstants>TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
- <DebugType>pdbonly</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>true</Optimize>\r
- <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <!-- Set AddAdditionalExplicitAssemblyReferences to false, otherwise if targetting .NET4.0, \r
- Microsoft.NETFramework.props will force a dependency on the assembly System.Core. This\r
- is a problem to compile the Mono mscorlib.dll -->\r
- <PropertyGroup>\r
- <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>\r
- </PropertyGroup>\r
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
- <ItemGroup>\r
- <Compile Include="AssemblyInfo.cs" />\r
- <Compile Include="TypeForwarders.cs" />\r </ItemGroup>\r
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
- Other similar extension points exist, see Microsoft.Common.targets.\r
- <Target Name="BeforeBuild">\r
- </Target>\r
- <Target Name="AfterBuild">\r
- </Target>\r
- -->\r
- <PropertyGroup>\r
- <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PreBuildEvent>\r
- <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PostBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../System/System-net_4_x.csproj">\r
- <Project>{2762E921-91A8-4C87-91E9-BA628013F753}</Project>\r
- <Name>System-net_4_x</Name>\r
- </ProjectReference>\r
- </ItemGroup>\r
- <ItemGroup>\r
- <Folder Include="Properties\" />\r
- </ItemGroup>\r
-</Project>\r
-
+++ /dev/null
-MCS_BUILD_DIR = ../../../build
-
-thisdir = class/Facades/System.Private.CoreLib.InteropServices
-SUBDIRS =
-include $(MCS_BUILD_DIR)/rules.make
-
-LIBRARY_SUBDIR = Facades
-LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades
-
-LIBRARY = System.Private.CoreLib.InteropServices.dll
-
-KEY_FILE = ../../msfinal.pub
-SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699
-LIB_REFS = System
-LIB_MCS_FLAGS = $(SIGN_FLAGS)
-
-PLATFORM_DEBUG_FLAGS =
-
-NO_TEST = yes
-
-include $(MCS_BUILD_DIR)/library.make
-
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <PropertyGroup>\r
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
- <ProductVersion>9.0.30729</ProductVersion>\r
- <SchemaVersion>2.0</SchemaVersion>\r
- <ProjectGuid>{BE4A05DF-5630-4E80-9521-7B4216229A60}</ProjectGuid>\r
- <OutputType>Library</OutputType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <OutputPath>./../../../class/lib/net_4_x/Facades</OutputPath>\r
- <NoStdLib>True</NoStdLib>\r
- <NoConfig>True</NoConfig>\r
- \r
- <AppDesignerFolder>Properties</AppDesignerFolder>\r
- <RootNamespace>\r
- </RootNamespace>\r
- <AssemblyName>System.Private.CoreLib.InteropServices</AssemblyName>\r
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
- <FileAlignment>512</FileAlignment>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <SignAssembly>true</SignAssembly>\r
- <DelaySign>true</DelaySign>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <AssemblyOriginatorKeyFile>../../msfinal.pub</AssemblyOriginatorKeyFile>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
- <DebugSymbols>true</DebugSymbols>\r
- <DebugType>full</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>false</Optimize>\r
- <DefineConstants>DEBUG;TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
- <DebugType>pdbonly</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>true</Optimize>\r
- <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <!-- Set AddAdditionalExplicitAssemblyReferences to false, otherwise if targetting .NET4.0, \r
- Microsoft.NETFramework.props will force a dependency on the assembly System.Core. This\r
- is a problem to compile the Mono mscorlib.dll -->\r
- <PropertyGroup>\r
- <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>\r
- </PropertyGroup>\r
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
- <ItemGroup>\r
- <Compile Include="AssemblyInfo.cs" />\r
- <Compile Include="TypeForwarders.cs" />\r </ItemGroup>\r
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
- Other similar extension points exist, see Microsoft.Common.targets.\r
- <Target Name="BeforeBuild">\r
- </Target>\r
- <Target Name="AfterBuild">\r
- </Target>\r
- -->\r
- <PropertyGroup>\r
- <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
- <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
-\r
- <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../System/System-net_4_x.csproj">\r
- <Project>{2762E921-91A8-4C87-91E9-BA628013F753}</Project>\r
- <Name>System-net_4_x</Name>\r
- </ProjectReference>\r
- </ItemGroup>\r
- <ItemGroup>\r
- <Folder Include="Properties\" />\r
- </ItemGroup>\r
-</Project>\r
-
+++ /dev/null
-TypeForwarders.cs
-AssemblyInfo.cs
-
+++ /dev/null
-//
-// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.CallingConvention))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.DllImportAttribute))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.GCHandle))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.GCHandleType))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.SafeHandle))]
-
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(Internal.Reflection.Execution.PayForPlayExperience.MissingMetadataExceptionCreator))]
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.DependencyReductionTypeRemoved))]
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.PreInitializedAttribute))]
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.InteropExtensions))]
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.NativeCallableAttributes))]
-//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.RuntimeImportAttribute))]
[assembly: AssemblyCompany ("Xamarin, Inc.")]
[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
[assembly: AssemblyCopyright ("Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)")]
-[assembly: AssemblyVersion ("4.0.0.0")]
+[assembly: AssemblyVersion ("4.0.1.0")]
[assembly: AssemblyInformationalVersion ("4.0.0.0")]
[assembly: AssemblyFileVersion ("4.0.0.0")]
[assembly: AssemblyDelaySign (true)]
[assembly: AssemblyCompany ("Xamarin, Inc.")]
[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
[assembly: AssemblyCopyright ("Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)")]
-[assembly: AssemblyVersion ("4.0.0.0")]
+[assembly: AssemblyVersion ("4.0.1.0")]
[assembly: AssemblyInformationalVersion ("4.0.0.0")]
[assembly: AssemblyFileVersion ("4.0.0.0")]
[assembly: AssemblyDelaySign (true)]
[assembly: AssemblyCompany ("Xamarin, Inc.")]
[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
[assembly: AssemblyCopyright ("Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)")]
-[assembly: AssemblyVersion ("4.0.0.0")]
+[assembly: AssemblyVersion ("4.0.1.0")]
[assembly: AssemblyInformationalVersion ("4.0.0.0")]
[assembly: AssemblyFileVersion ("4.0.0.0")]
[assembly: AssemblyDelaySign (true)]
{
public static class TypeExtensions
{
- public static ConstructorInfo GetConstructor(Type type, Type[] types)
+ public static ConstructorInfo GetConstructor(this Type type, Type[] types)
{
Requires.NotNull(type, nameof(type));
return type.GetConstructor(types);
}
- public static ConstructorInfo[] GetConstructors(Type type)
+ public static ConstructorInfo[] GetConstructors(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetConstructors();
}
- public static ConstructorInfo[] GetConstructors(Type type, BindingFlags bindingAttr)
+ public static ConstructorInfo[] GetConstructors(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetConstructors(bindingAttr);
}
- public static MemberInfo[] GetDefaultMembers(Type type)
+ public static MemberInfo[] GetDefaultMembers(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetDefaultMembers();
}
- public static EventInfo GetEvent(Type type, string name)
+ public static EventInfo GetEvent(this Type type, string name)
{
Requires.NotNull(type, nameof(type));
return type.GetEvent(name);
}
- public static EventInfo GetEvent(Type type, string name, BindingFlags bindingAttr)
+ public static EventInfo GetEvent(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetEvent(name, bindingAttr);
}
- public static EventInfo[] GetEvents(Type type)
+ public static EventInfo[] GetEvents(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetEvents();
}
- public static EventInfo[] GetEvents(Type type, BindingFlags bindingAttr)
+ public static EventInfo[] GetEvents(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetEvents(bindingAttr);
}
- public static FieldInfo GetField(Type type, string name)
+ public static FieldInfo GetField(this Type type, string name)
{
Requires.NotNull(type, nameof(type));
return type.GetField(name);
}
- public static FieldInfo GetField(Type type, string name, BindingFlags bindingAttr)
+ public static FieldInfo GetField(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetField(name, bindingAttr);
}
- public static FieldInfo[] GetFields(Type type)
+ public static FieldInfo[] GetFields(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetFields();
}
- public static FieldInfo[] GetFields(Type type, BindingFlags bindingAttr)
+ public static FieldInfo[] GetFields(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetFields(bindingAttr);
}
- public static Type[] GetGenericArguments(Type type)
+ public static Type[] GetGenericArguments(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetGenericArguments();
}
- public static Type[] GetInterfaces(Type type)
+ public static Type[] GetInterfaces(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetInterfaces();
}
- public static MemberInfo[] GetMember(Type type, string name)
+ public static MemberInfo[] GetMember(this Type type, string name)
{
Requires.NotNull(type, nameof(type));
return type.GetMember(name);
}
- public static MemberInfo[] GetMember(Type type, string name, BindingFlags bindingAttr)
+ public static MemberInfo[] GetMember(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetMember(name, bindingAttr);
}
- public static MemberInfo[] GetMembers(Type type)
+ public static MemberInfo[] GetMembers(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetMembers();
}
- public static MemberInfo[] GetMembers(Type type, BindingFlags bindingAttr)
+ public static MemberInfo[] GetMembers(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetMembers(bindingAttr);
}
- public static MethodInfo GetMethod(Type type, string name)
+ public static MethodInfo GetMethod(this Type type, string name)
{
Requires.NotNull(type, nameof(type));
return type.GetMethod(name);
}
- public static MethodInfo GetMethod(Type type, string name, BindingFlags bindingAttr)
+ public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetMethod(name, bindingAttr);
}
- public static MethodInfo GetMethod(Type type, string name, Type[] types)
+ public static MethodInfo GetMethod(this Type type, string name, Type[] types)
{
Requires.NotNull(type, nameof(type));
return type.GetMethod(name, types);
}
- public static MethodInfo[] GetMethods(Type type)
+ public static MethodInfo[] GetMethods(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetMethods();
}
- public static MethodInfo[] GetMethods(Type type, BindingFlags bindingAttr)
+ public static MethodInfo[] GetMethods(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetMethods(bindingAttr);
}
- public static Type GetNestedType(Type type, string name, BindingFlags bindingAttr)
+ public static Type GetNestedType(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetNestedType(name, bindingAttr);
}
- public static Type[] GetNestedTypes(Type type, BindingFlags bindingAttr)
+ public static Type[] GetNestedTypes(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetNestedTypes(bindingAttr);
}
- public static PropertyInfo[] GetProperties(Type type)
+ public static PropertyInfo[] GetProperties(this Type type)
{
Requires.NotNull(type, nameof(type));
return type.GetProperties();
}
- public static PropertyInfo[] GetProperties(Type type, BindingFlags bindingAttr)
+ public static PropertyInfo[] GetProperties(this Type type, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetProperties(bindingAttr);
}
- public static PropertyInfo GetProperty(Type type, string name)
+ public static PropertyInfo GetProperty(this Type type, string name)
{
Requires.NotNull(type, nameof(type));
return type.GetProperty(name);
}
- public static PropertyInfo GetProperty(Type type, string name, BindingFlags bindingAttr)
+ public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingAttr)
{
Requires.NotNull(type, nameof(type));
return type.GetProperty(name, bindingAttr);
}
- public static PropertyInfo GetProperty(Type type, string name, Type returnType)
+ public static PropertyInfo GetProperty(this Type type, string name, Type returnType)
{
Requires.NotNull(type, nameof(type));
return type.GetProperty(name, returnType);
}
- public static PropertyInfo GetProperty(Type type, string name, Type returnType, Type[] types)
+ public static PropertyInfo GetProperty(this Type type, string name, Type returnType, Type[] types)
{
Requires.NotNull(type, nameof(type));
return type.GetProperty(name, returnType, types);
}
- public static bool IsAssignableFrom(Type type, Type c)
+ public static bool IsAssignableFrom(this Type type, Type c)
{
Requires.NotNull(type, nameof(type));
return type.IsAssignableFrom(c);
}
- public static bool IsInstanceOfType(Type type, object o)
+ public static bool IsInstanceOfType(this Type type, object o)
{
Requires.NotNull(type, nameof(type));
return type.IsInstanceOfType(o);
public static class AssemblyExtensions
{
- public static Type[] GetExportedTypes(Assembly assembly)
+ public static Type[] GetExportedTypes(this Assembly assembly)
{
Requires.NotNull(assembly, nameof(assembly));
return assembly.GetExportedTypes();
}
- public static Module[] GetModules(Assembly assembly)
+ public static Module[] GetModules(this Assembly assembly)
{
Requires.NotNull(assembly, nameof(assembly));
return assembly.GetModules();
}
- public static Type[] GetTypes(Assembly assembly)
+ public static Type[] GetTypes(this Assembly assembly)
{
Requires.NotNull(assembly, nameof(assembly));
return assembly.GetTypes();
public static class EventInfoExtensions
{
- public static MethodInfo GetAddMethod(EventInfo eventInfo)
+ public static MethodInfo GetAddMethod(this EventInfo eventInfo)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetAddMethod();
}
- public static MethodInfo GetAddMethod(EventInfo eventInfo, bool nonPublic)
+ public static MethodInfo GetAddMethod(this EventInfo eventInfo, bool nonPublic)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetAddMethod(nonPublic);
}
- public static MethodInfo GetRaiseMethod(EventInfo eventInfo)
+ public static MethodInfo GetRaiseMethod(this EventInfo eventInfo)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetRaiseMethod();
}
- public static MethodInfo GetRaiseMethod(EventInfo eventInfo, bool nonPublic)
+ public static MethodInfo GetRaiseMethod(this EventInfo eventInfo, bool nonPublic)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetRaiseMethod(nonPublic);
}
- public static MethodInfo GetRemoveMethod(EventInfo eventInfo)
+ public static MethodInfo GetRemoveMethod(this EventInfo eventInfo)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetRemoveMethod();
}
- public static MethodInfo GetRemoveMethod(EventInfo eventInfo, bool nonPublic)
+ public static MethodInfo GetRemoveMethod(this EventInfo eventInfo, bool nonPublic)
{
Requires.NotNull(eventInfo, nameof(eventInfo));
return eventInfo.GetRemoveMethod(nonPublic);
public static class MethodInfoExtensions
{
- public static MethodInfo GetBaseDefinition(MethodInfo method)
+ public static MethodInfo GetBaseDefinition(this MethodInfo method)
{
Requires.NotNull(method, nameof(method));
return method.GetBaseDefinition();
public static class PropertyInfoExtensions
{
- public static MethodInfo[] GetAccessors(PropertyInfo property)
+ public static MethodInfo[] GetAccessors(this PropertyInfo property)
{
Requires.NotNull(property, nameof(property));
return property.GetAccessors();
}
- public static MethodInfo[] GetAccessors(PropertyInfo property, bool nonPublic)
+ public static MethodInfo[] GetAccessors(this PropertyInfo property, bool nonPublic)
{
Requires.NotNull(property, nameof(property));
return property.GetAccessors(nonPublic);
}
- public static MethodInfo GetGetMethod(PropertyInfo property)
+ public static MethodInfo GetGetMethod(this PropertyInfo property)
{
Requires.NotNull(property, nameof(property));
return property.GetGetMethod();
}
- public static MethodInfo GetGetMethod(PropertyInfo property, bool nonPublic)
+ public static MethodInfo GetGetMethod(this PropertyInfo property, bool nonPublic)
{
Requires.NotNull(property, nameof(property));
return property.GetGetMethod(nonPublic);
}
- public static MethodInfo GetSetMethod(PropertyInfo property)
+ public static MethodInfo GetSetMethod(this PropertyInfo property)
{
Requires.NotNull(property, nameof(property));
return property.GetSetMethod();
}
- public static MethodInfo GetSetMethod(PropertyInfo property, bool nonPublic)
+ public static MethodInfo GetSetMethod(this PropertyInfo property, bool nonPublic)
{
Requires.NotNull(property, nameof(property));
return property.GetSetMethod(nonPublic);
// THE SOFTWARE.
//
-#if !FULL_AOT_RUNTIME
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComImportAttribute))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.DispatchWrapper))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ErrorWrapper))]
-#endif
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.DataMisalignedException))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.DllNotFoundException))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Reflection.Missing))]
// THE SOFTWARE.
//
+using System.Runtime.InteropServices;
+
namespace System.Security
{
public static class SecureStringMarshal
{
public static IntPtr SecureStringToCoTaskMemAnsi (SecureString s)
{
- throw new NotImplementedException ();
+ return Marshal.SecureStringToCoTaskMemAnsi (s);
}
public static IntPtr SecureStringToCoTaskMemUnicode (SecureString s)
{
- throw new NotImplementedException ();
+ return Marshal.SecureStringToCoTaskMemUnicode (s);
}
public static IntPtr SecureStringToGlobalAllocAnsi (SecureString s)
{
- throw new NotImplementedException ();
+ return Marshal.SecureStringToGlobalAllocAnsi (s);
}
public static IntPtr SecureStringToGlobalAllocUnicode (SecureString s)
{
- throw new NotImplementedException ();
+ return Marshal.SecureStringToGlobalAllocUnicode (s);
}
}
}
{
public class ServiceController : IDisposable
{
- [MonoTODO]
public bool CanPauseAndContinue
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public bool CanShutdown
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public bool CanStop
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceController[] DependentServices
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public string DisplayName
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public string MachineName
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public SafeHandle ServiceHandle
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public string ServiceName
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceController[] ServicesDependedOn
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceType ServiceType
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceStartMode StartType
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceControllerStatus Status
{
get
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
- [MonoTODO]
public ServiceController (string name)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public ServiceController (string name, string machineName)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Continue ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Dispose ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
protected virtual void Dispose (bool disposing)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public static ServiceController[] GetDevices ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public static ServiceController[] GetDevices (string machineName)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public static ServiceController[] GetServices ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public static ServiceController[] GetServices (string machineName)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Pause ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Refresh ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Start ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Start (string[] args)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void Stop ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void WaitForStatus (ServiceControllerStatus desiredStatus)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public void WaitForStatus (ServiceControllerStatus desiredStatus, TimeSpan timeout)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
}
{
public class TimeoutException : Exception
{
- [MonoTODO]
public TimeoutException ()
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public TimeoutException (string message)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
- [MonoTODO]
public TimeoutException (string message, Exception innerException)
{
- throw new NotImplementedException ();
+ throw new PlatformNotSupportedException ();
}
}
}
{
public static class ThreadingAclExtensions
{
- [MonoTODO]
- public static EventWaitHandleSecurity GetAccessControl (EventWaitHandle handle)
+ public static EventWaitHandleSecurity GetAccessControl (this EventWaitHandle handle)
{
- throw new NotImplementedException ();
+ if (handle == null)
+ throw new ArgumentNullException (nameof (handle));
+
+ return handle.GetAccessControl ();
}
- [MonoTODO]
- public static void SetAccessControl (EventWaitHandle handle, EventWaitHandleSecurity eventSecurity)
+ public static void SetAccessControl (this EventWaitHandle handle, EventWaitHandleSecurity eventSecurity)
{
- throw new NotImplementedException ();
+ if (handle == null)
+ throw new ArgumentNullException (nameof (handle));
+
+ handle.SetAccessControl (eventSecurity);
}
- [MonoTODO]
- public static MutexSecurity GetAccessControl (Mutex mutex)
+ public static MutexSecurity GetAccessControl (this Mutex mutex)
{
- throw new NotImplementedException ();
+ if (mutex == null)
+ throw new ArgumentNullException (nameof (mutex));
+
+ return mutex.GetAccessControl ();
}
- [MonoTODO]
- public static void SetAccessControl (Mutex mutex, MutexSecurity mutexSecurity)
+ public static void SetAccessControl (this Mutex mutex, MutexSecurity mutexSecurity)
{
- throw new NotImplementedException ();
+ if (mutex == null)
+ throw new ArgumentNullException (nameof (mutex));
+
+ mutex.SetAccessControl (mutexSecurity);
}
- [MonoTODO]
- public static SemaphoreSecurity GetAccessControl (Semaphore semaphore)
+ public static SemaphoreSecurity GetAccessControl (this Semaphore semaphore)
{
- throw new NotImplementedException ();
+ if (semaphore == null)
+ throw new ArgumentNullException (nameof (semaphore));
+
+ return semaphore.GetAccessControl ();
}
- [MonoTODO]
- public static void SetAccessControl (Semaphore semaphore, SemaphoreSecurity semaphoreSecurity)
+ public static void SetAccessControl (this Semaphore semaphore, SemaphoreSecurity semaphoreSecurity)
{
- throw new NotImplementedException ();
+ if (semaphore == null)
+ throw new ArgumentNullException (nameof (semaphore));
+
+ semaphore.SetAccessControl (semaphoreSecurity);
}
}
}
\ No newline at end of file
System.Security.Cryptography.Hashing.Algorithms System.Security.Cryptography.RSA System.Security.Cryptography.RandomNumberGenerator \
System.Security.Principal.Windows System.Threading.Thread System.Threading.ThreadPool \
System.Xml.XPath System.Xml.XmlDocument System.Xml.Xsl.Primitives Microsoft.Win32.Registry.AccessControl System.Diagnostics.StackTrace System.Globalization.Extensions \
-System.IO.FileSystem.AccessControl System.Private.CoreLib.InteropServices System.Reflection.TypeExtensions \
+System.IO.FileSystem.AccessControl System.Reflection.TypeExtensions \
System.Security.SecureString System.Threading.AccessControl System.Threading.Overlapped System.Xml.XPath.XDocument \
System.Security.Cryptography.Primitives System.Text.Encoding.CodePages System.IO.FileSystem.Watcher \
System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes
ProjectRootElement.Create (XmlReader.Create (new StringReader (" <root/>")));
Assert.Fail ("should throw InvalidProjectFileException");
} catch (InvalidProjectFileException ex) {
- #if NET_4_5
Assert.AreEqual (1, ex.LineNumber, "#1");
// it is very interesting, but unlike XmlReader.LinePosition it returns the position for '<'.
Assert.AreEqual (2, ex.ColumnNumber, "#2");
- #endif
}
}
ProjectRootElement.Create (xml);
Assert.Fail ("should throw InvalidProjectFileException");
} catch (InvalidProjectFileException ex) {
- #if NET_4_5
Assert.AreEqual (1, ex.LineNumber, "#1");
// unlike unexpected element case which returned the position for '<', it does return the name start char...
Assert.AreEqual (70, ex.ColumnNumber, "#2");
- #endif
}
}
{
var g = ProjectCollection.GlobalProjectCollection;
Assert.AreEqual (0, g.GlobalProperties.Count, "#1");
- #if NET_4_5
Assert.IsTrue (g.GlobalProperties.IsReadOnly, "#2");
- #endif
}
[Test]
var ts = new Toolset ("4.3", "c:\\", ProjectCollection.GlobalProjectCollection, null);
Assert.IsNotNull (ts.Properties, "#1");
Assert.AreEqual (0, ts.Properties.Count, "#2");
-#if NET_4_5
Assert.IsNull (ts.DefaultSubToolsetVersion, "#3");
Assert.IsNotNull (ts.SubToolsets, "#4");
Assert.AreEqual (0, ts.SubToolsets.Count, "#5");
-#endif
Assert.AreEqual ("c:\\", ts.ToolsPath, "#6");
Assert.AreEqual ("4.3", ts.ToolsVersion, "#7");
}
var root = ProjectRootElement.Create (xml);
root.FullPath = "ProjectInstanceTest.DependsOnTargets.proj";
var proj = new ProjectInstance (root);
-#if NET_4_5
Assert.AreEqual (2, proj.Targets.Count, "#1");
-#endif
Assert.IsFalse (proj.Build ("Bar", new ILogger [0]), "#2");
}
[TestFixture]
public class ProjectTaskInstanceTest
{
-#if NET_4_5
[Test]
public void OutputPropertyExists ()
{
Assert.AreEqual (string.Empty, foo.Outputs, "#6");
Assert.AreEqual ("True", proj.GetPropertyValue ("C"), "#7");
}
-#endif
}
}
// Compatibility with versions < 3.5.0\r
int n;\r
\r
- try {\r
+ if (UnsafeNativeMethods.use_sqlite3_open_v2) {\r
n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero);\r
- } catch (EntryPointNotFoundException) {\r
+ } else {\r
Console.WriteLine ("Your sqlite3 version is old - please upgrade to at least v3.5.0!");\r
n = UnsafeNativeMethods.sqlite3_open (ToUTF8 (strFilename), out db);\r
}\r
#else\r
ResetConnection(db);\r
int n;\r
- try {\r
+ if (UnsafeNativeMethods.use_sqlite3_close_v2) {\r
n = UnsafeNativeMethods.sqlite3_close_v2(db);\r
- } catch (EntryPointNotFoundException) {\r
+ } else {\r
n = UnsafeNativeMethods.sqlite3_close(db);\r
}\r
#endif\r
#endif\r
internal static class UnsafeNativeMethods\r
{\r
+ internal static readonly bool use_sqlite3_close_v2 = false;\r
+ internal static readonly bool use_sqlite3_open_v2 = false;\r
+ internal static readonly bool use_sqlite3_create_function_v2 = false;\r
+ static UnsafeNativeMethods()\r
+ {\r
+ // calculate the version number parts\r
+ // https://www.sqlite.org/c3ref/c_source_id.html\r
+ // (<major> * 1000000) + (<minor> * 1000) + (<release>)\r
+ int versionNumber = sqlite3_libversion_number();\r
+ int release = versionNumber % 1000;\r
+ int minor = (versionNumber / 1000) % 1000;\r
+ int major = versionNumber / 1000000;\r
+ Version version = new Version(major, minor, release);\r
+\r
+ // set the various versions\r
+ // https://sqlite.org/changes.html\r
+ use_sqlite3_open_v2 = version >= new Version(3, 5, 0);\r
+ use_sqlite3_close_v2 = version >= new Version(3, 7, 14);\r
+ use_sqlite3_create_function_v2 = version >= new Version(3, 7, 3);\r
+ }\r
+\r
#if !SQLITE_STANDARD\r
\r
#if !USE_INTEROP_DLL\r
#endif\r
internal static extern int sqlite3_free (IntPtr ptr);\r
\r
+#if !PLATFORM_COMPACTFRAMEWORK\r
+ [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]\r
+#else\r
+ [DllImport(SQLITE_DLL)]\r
+#endif\r
+ internal static extern int sqlite3_libversion_number();\r
+\r
#endregion\r
}\r
\r
}
[MethodImplAttribute (MethodImplOptions.NoInlining)]
-#if NET_4_5
[StateMachine (typeof (int))]
-#endif
public static void locals2<T> (string[] args, int arg, T t, ref string rs, ref AStruct astruct) {
long i = 42;
string s = "AB";
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static void unhandled_exception_user () {
-#if NET_4_5
System.Threading.Tasks.Task.Factory.StartNew (() => {
Throw ();
});
Thread.Sleep (10000);
-#endif
}
[MethodImplAttribute (MethodImplOptions.NoInlining)]
Assert.AreEqual ("Exception", ex.Exception.Type.Name);
}
-#if NET_4_5
// out argument
m = t.GetMethod ("invoke_out");
var out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) }, InvokeOptions.ReturnOutArgs);
out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) });
out_args = out_task.Result.OutArgs;
Assert.IsNull (out_args);
-#endif
// newobj
m = t.GetMethod (".ctor");
v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") }, InvokeOptions.Virtual);
AssertValue ("ABC", v);
-#if NET_4_5
// instance
m = t.GetMethod ("invoke_pass_ref");
var task = this_obj.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
m = t.GetMethod ("invoke_static_pass_ref");
task = t.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
AssertValue ("ABC", task.Result);
-#endif
// Argument checking
v = t.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) });
AssertValue (1, (v as StructMirror)["i"]);
-#if NET_4_5
// Invoke a method which changes state
s = frame.GetArgument (1) as StructMirror;
t = s.Type;
m = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString");
v = s.InvokeMethod (e.Thread, m, null, InvokeOptions.Virtual);
AssertValue ("42", v);
-#endif
}
[Test]
vm = null;
}
-#if NET_4_5
[Test]
public void UnhandledExceptionUserCode () {
vm.Detach ();
vm.Exit (0);
vm = null;
}
-#endif
[Test]
public void GCWhileSuspended () {
namespace MonoTests.System.ComponentModel.DataAnnotations
{
-#if NET_4_5
[TestFixture]
public class CompareAttributeTest
{
Assert.IsNotNull (sla.GetValidationResult (DateTime.Now, ctx), "#B-4");
}
}
-#endif
}
namespace MonoTests.System.ComponentModel.DataAnnotations
{
-#if NET_4_5
[TestFixture]
public class CreditCardAttributeTest
{
Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-8");
}
}
-#endif
}
namespace MonoTests.System.ComponentModel.DataAnnotations
{
-#if NET_4_5
[TestFixture]
public class EmailAddressAttributeTest
{
Assert.IsFalse (sla.IsValid (InvalidAddresses[i]), "#B1-{0}", i);
}
}
-#endif
}
namespace MonoTests.System.ComponentModel.DataAnnotations
{
-#if NET_4_5
[TestFixture]
public class FileExtensionsAttributeTest
{
Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-8");
}
}
-#endif
}
namespace MonoTests.System.ComponentModel.DataAnnotations
{
-#if NET_4_5
[TestFixture]
public class PhoneAttributeTest
{
Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-7");
}
}
-#endif
}
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
#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
using System;
using System.IO;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
using System.Collections;
using System.ComponentModel;
using System.Data;
throw new NotImplementedException ();
}
+ override public Task<T> GetFieldValueAsync<T> (int i, CancellationToken cancellationToken)
+ {
+ return base.GetFieldValueAsync<T> (i, cancellationToken);
+ }
+
+ override public Stream GetStream (int i)
+ {
+ return base.GetStream (i);
+ }
+ override public TextReader GetTextReader (int i)
+ {
+ return base.GetTextReader (i);
+ }
+
+ override public Task<bool> IsDBNullAsync (int i, CancellationToken cancellationToken)
+ {
+ return base.IsDBNullAsync (i, cancellationToken);
+ }
+
#endregion // Methods
}
}
{
}
- #if NET_4_5
[Test]
public void GetFieldValueTest ()
{
Assert.IsFalse (dataReader.Read (), "#5");
}
- #endif //NET_4_5
}
}
// BootstrapContextTest.cs - NUnit Test Cases for System.IdentityModel.Tokens.BootstrapContext
//
-#if NET_4_5
using System;
using System.IO;
using System.IdentityModel.Tokens;
}
}
}
-#endif
[assembly: AssemblyCompany (Consts.MonoCompany)]
[assembly: AssemblyProduct (Consts.MonoProduct)]
[assembly: AssemblyCopyright (Consts.MonoCopyright)]
-[assembly: AssemblyVersion (Consts.FxVersion)]
+[assembly: AssemblyVersion ("4.0.0.0")]
[assembly: SatelliteContractVersion (Consts.FxVersion)]
[assembly: AssemblyInformationalVersion (Consts.FxFileVersion)]
[assembly: AssemblyFileVersion (Consts.FxFileVersion)]
_params = new byte [0];
}
- public AlgorithmIdentifier (Oid algorithm)
+ public AlgorithmIdentifier (Oid oid)
{
- _oid = algorithm;
+ _oid = oid;
_params = new byte [0];
}
- public AlgorithmIdentifier (Oid algorithm, int keyLength)
+ public AlgorithmIdentifier (Oid oid, int keyLength)
{
- _oid = algorithm;
+ _oid = oid;
_length = keyLength;
_params = new byte [0];
}
{
}
- public ContentInfo (Oid oid, byte[] content)
+ public ContentInfo (Oid contentType, byte[] content)
{
- if (oid == null)
- throw new ArgumentNullException ("oid");
+ if (contentType == null)
+ throw new ArgumentNullException ("contentType");
if (content == null)
throw new ArgumentNullException ("content");
- _oid = oid;
+ _oid = contentType;
_content = content;
}
_uattribs = new CryptographicAttributeObjectCollection ();
}
- public EnvelopedCms (ContentInfo content) : this ()
+ public EnvelopedCms (ContentInfo contentInfo) : this ()
{
- if (content == null)
- throw new ArgumentNullException ("content");
+ if (contentInfo == null)
+ throw new ArgumentNullException ("contentInfo");
- _content = content;
+ _content = contentInfo;
}
public EnvelopedCms (ContentInfo contentInfo, AlgorithmIdentifier encryptionAlgorithm)
return new DefaultAddressHeader (value);
}
- public static AddressHeader CreateAddressHeader (object value, XmlObjectSerializer formatter)
+ public static AddressHeader CreateAddressHeader (object value, XmlObjectSerializer serializer)
{
- return new DefaultAddressHeader (value, formatter);
+ return new DefaultAddressHeader (value, serializer);
}
public static AddressHeader CreateAddressHeader (string name, string ns, object value)
}
public static AddressHeader CreateAddressHeader (string name, string ns, object value,
- XmlObjectSerializer formatter)
+ XmlObjectSerializer serializer)
{
- if (formatter == null)
- throw new ArgumentNullException ("formatter");
- return new DefaultAddressHeader (name, ns, value, formatter);
+ if (serializer == null)
+ throw new ArgumentNullException ("serializer");
+ return new DefaultAddressHeader (name, ns, value, serializer);
}
public override bool Equals (object obj)
return GetValue<T> (new DataContractSerializer (typeof (T)));
}
- public T GetValue<T> (XmlObjectSerializer formatter)
+ public T GetValue<T> (XmlObjectSerializer serializer)
{
- return (T) formatter.ReadObject (GetAddressHeaderReader ());
+ return (T) serializer.ReadObject (GetAddressHeaderReader ());
}
protected abstract void OnWriteAddressHeaderContents (XmlDictionaryWriter writer);
{
}
- public AddressHeaderCollection (IEnumerable<AddressHeader> headers)
- : base (GetList (headers))
+ public AddressHeaderCollection (IEnumerable<AddressHeader> addressHeaders)
+ : base (GetList (addressHeaders))
{
}
BindingElementCollection elements; // for internal use
public BindingContext (CustomBinding binding,
- BindingParameterCollection parms)
+ BindingParameterCollection parameters)
{
if (binding == null)
throw new ArgumentNullException ("binding");
- if (parms == null)
- throw new ArgumentNullException ("parms");
+ if (parameters == null)
+ throw new ArgumentNullException ("parameters");
this.binding = binding;
- parameters = new BindingParameterCollection ();
- foreach (var item in parms)
- parameters.Add (item);
+ this.parameters = new BindingParameterCollection ();
+ foreach (var item in parameters)
+ this.parameters.Add (item);
this.elements = new BindingElementCollection ();
foreach (var item in binding.Elements)
this.elements.Add (item);
}
[MonoTODO]
- protected BindingElement (BindingElement other)
+ protected BindingElement (BindingElement elementToBeCloned)
{
}
{
}
- public BindingElementCollection (BindingElement [] bindings)
+ public BindingElementCollection (BindingElement [] elements)
{
- AddRange (bindings);
+ AddRange (elements);
}
- public BindingElementCollection (IEnumerable<BindingElement> bindings)
+ public BindingElementCollection (IEnumerable<BindingElement> elements)
{
- foreach (BindingElement e in bindings)
+ foreach (BindingElement e in elements)
Add (e);
}
{
ChannelManagerBase manager;
- protected ChannelBase (ChannelManagerBase manager)
+ protected ChannelBase (ChannelManagerBase channelManager)
{
- this.manager = manager;
+ this.manager = channelManager;
}
protected internal override TimeSpan DefaultCloseTimeout {
}
public TChannel CreateChannel (
- EndpointAddress remoteAddress)
+ EndpointAddress address)
{
- if (remoteAddress == null)
- throw new ArgumentNullException ("remoteAddress");
- return CreateChannel (remoteAddress, remoteAddress.Uri);
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ return CreateChannel (address, address.Uri);
}
public TChannel CreateChannel (
- EndpointAddress remoteAddress, Uri via)
+ EndpointAddress address, Uri via)
{
- if (remoteAddress == null)
- throw new ArgumentNullException ("remoteAddress");
+ if (address == null)
+ throw new ArgumentNullException ("address");
if (via == null)
throw new ArgumentNullException ("via");
ValidateCreateChannel ();
- var ch = OnCreateChannel (remoteAddress, via);
+ var ch = OnCreateChannel (address, via);
channels.Add (ch);
return ch;
}
protected abstract TChannel OnCreateChannel (
- EndpointAddress remoteAddress, Uri via);
+ EndpointAddress address, Uri via);
protected override void OnAbort ()
{
security = binding as ISecurityCapabilities;
}
- public CustomBinding (params BindingElement [] binding)
- : this ("CustomBinding", default_ns, binding)
+ public CustomBinding (params BindingElement [] bindingElementsInTopDownChannelStackOrder)
+ : this ("CustomBinding", default_ns, bindingElementsInTopDownChannelStackOrder)
{
}
- public CustomBinding (IEnumerable<BindingElement> bindingElements)
- : this (bindingElements, "CustomBinding", default_ns)
+ public CustomBinding (IEnumerable<BindingElement> bindingElementsInTopDownChannelStackOrder)
+ : this (bindingElementsInTopDownChannelStackOrder, "CustomBinding", default_ns)
{
}
public CustomBinding (string name, string ns,
- params BindingElement [] binding)
- : this (binding, name, ns)
+ params BindingElement [] bindingElementsInTopDownChannelStackOrder)
+ : this (bindingElementsInTopDownChannelStackOrder, name, ns)
{
}
[MonoTODO]
protected abstract bool OnTryCreateException (
- Message message, MessageFault fault, out Exception error);
+ Message message, MessageFault fault, out Exception exception);
[MonoTODO]
protected abstract bool OnTryCreateFaultMessage (
- Exception error, out Message message);
+ Exception exception, out Message message);
- public bool TryCreateException (Message message, MessageFault fault, out Exception error)
+ public bool TryCreateException (Message message, MessageFault fault, out Exception exception)
{
- return OnTryCreateException (message, fault, out error);
+ return OnTryCreateException (message, fault, out exception);
}
- public bool TryCreateFaultMessage (Exception error, out Message message)
+ public bool TryCreateFaultMessage (Exception exception, out Message message)
{
- return OnTryCreateFaultMessage (error, out message);
+ return OnTryCreateFaultMessage (exception, out message);
}
}
}
web_request.Timeout = (int) timeout.TotalMilliseconds;
+ web_request.KeepAlive = httpbe.KeepAliveEnabled;
// There is no SOAP Action/To header when AddressingVersion is None.
if (message.Version.Envelope.Equals (EnvelopeVersion.Soap11) ||
}
protected HttpTransportBindingElement (
- HttpTransportBindingElement other)
- : base (other)
+ HttpTransportBindingElement elementToBeCloned)
+ : base (elementToBeCloned)
{
- allow_cookies = other.allow_cookies;
- bypass_proxy_on_local = other.bypass_proxy_on_local;
- unsafe_ntlm_auth = other.unsafe_ntlm_auth;
- use_default_proxy = other.use_default_proxy;
- keep_alive_enabled = other.keep_alive_enabled;
- max_buffer_size = other.max_buffer_size;
- host_cmp_mode = other.host_cmp_mode;
- proxy_address = other.proxy_address;
- realm = other.realm;
- transfer_mode = other.transfer_mode;
+ allow_cookies = elementToBeCloned.allow_cookies;
+ bypass_proxy_on_local = elementToBeCloned.bypass_proxy_on_local;
+ unsafe_ntlm_auth = elementToBeCloned.unsafe_ntlm_auth;
+ use_default_proxy = elementToBeCloned.use_default_proxy;
+ keep_alive_enabled = elementToBeCloned.keep_alive_enabled;
+ max_buffer_size = elementToBeCloned.max_buffer_size;
+ host_cmp_mode = elementToBeCloned.host_cmp_mode;
+ proxy_address = elementToBeCloned.proxy_address;
+ realm = elementToBeCloned.realm;
+ transfer_mode = elementToBeCloned.transfer_mode;
// FIXME: it does not look safe
- timeouts = other.timeouts;
- auth_scheme = other.auth_scheme;
- proxy_auth_scheme = other.proxy_auth_scheme;
-
- DecompressionEnabled = other.DecompressionEnabled;
- LegacyExtendedProtectionPolicy = other.LegacyExtendedProtectionPolicy;
- ExtendedProtectionPolicy = other.ExtendedProtectionPolicy;
- cookie_manager = other.cookie_manager;
+ timeouts = elementToBeCloned.timeouts;
+ auth_scheme = elementToBeCloned.auth_scheme;
+ proxy_auth_scheme = elementToBeCloned.proxy_auth_scheme;
+
+ DecompressionEnabled = elementToBeCloned.DecompressionEnabled;
+ LegacyExtendedProtectionPolicy = elementToBeCloned.LegacyExtendedProtectionPolicy;
+ ExtendedProtectionPolicy = elementToBeCloned.ExtendedProtectionPolicy;
+ cookie_manager = elementToBeCloned.cookie_manager;
}
[DefaultValue (AuthenticationSchemes.Anonymous)]
}
protected HttpsTransportBindingElement (
- HttpsTransportBindingElement other)
- : base (other)
+ HttpsTransportBindingElement elementToBeCloned)
+ : base (elementToBeCloned)
{
- req_cli_cert = other.req_cli_cert;
+ req_cli_cert = elementToBeCloned.req_cli_cert;
}
public bool RequireClientCertificate {
return OnGetBody<T> (GetReaderAtBodyContents ());
}
- public T GetBody<T> (XmlObjectSerializer xmlFormatter)
+ public T GetBody<T> (XmlObjectSerializer serializer)
{
// FIXME: Somehow use OnGetBody() here as well?
- return (T)xmlFormatter.ReadObject (GetReaderAtBodyContents ());
+ return (T)serializer.ReadObject (GetReaderAtBodyContents ());
}
protected virtual T OnGetBody<T> (XmlDictionaryReader reader)
// 5)
public static Message CreateMessage (MessageVersion version,
- string action, object body, XmlObjectSerializer xmlFormatter)
+ string action, object body, XmlObjectSerializer serializer)
{
return body == null ?
CreateMessage (version, action) :
CreateMessage (
version, action,
- new XmlObjectSerializerBodyWriter (body, xmlFormatter));
+ new XmlObjectSerializerBodyWriter (body, serializer));
}
// 6)
[MonoTODO]
public
- MessageEncodingBindingElement (MessageEncodingBindingElement source)
+ MessageEncodingBindingElement (MessageEncodingBindingElement elementToBeCloned)
{
- MessageVersion = source.MessageVersion;
+ MessageVersion = elementToBeCloned.MessageVersion;
}
public abstract MessageEncoderFactory
public abstract MessageVersion MessageVersion { get; set; }
- public override T GetProperty<T> (BindingContext ctx)
+ public override T GetProperty<T> (BindingContext context)
{
if (typeof (T) == typeof (MessageVersion))
return (T) (object) MessageVersion;
- return ctx.GetInnerProperty<T> ();
+ return context.GetInnerProperty<T> ();
}
#if !MOBILE && !XAMMAC_4_5
return GetDetail<T> (new DataContractSerializer (typeof (T)));
}
- public T GetDetail<T> (XmlObjectSerializer formatter)
+ public T GetDetail<T> (XmlObjectSerializer serializer)
{
if (!HasDetail)
throw new InvalidOperationException ("This message does not have details.");
- return (T) formatter.ReadObject (GetReaderAtDetailContents ());
+ return (T) serializer.ReadObject (GetReaderAtDetailContents ());
}
public XmlDictionaryReader GetReaderAtDetailContents ()
return CreateHeader (name, ns, value, default_must_understand);
}
- public static MessageHeader CreateHeader (string name, string ns, object value, bool must_understand)
+ public static MessageHeader CreateHeader (string name, string ns, object value, bool mustUnderstand)
{
- return CreateHeader (name, ns, value, must_understand, default_actor);
+ return CreateHeader (name, ns, value, mustUnderstand, default_actor);
}
- public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter)
+ public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer)
{
- return CreateHeader (name, ns, value, formatter, default_must_understand,
+ return CreateHeader (name, ns, value, serializer, default_must_understand,
default_actor, default_relay);
}
public static MessageHeader CreateHeader (string name, string ns, object value,
- bool must_understand, string actor)
+ bool mustUnderstand, string actor)
{
- return CreateHeader (name, ns, value, must_understand, actor, default_relay);
+ return CreateHeader (name, ns, value, mustUnderstand, actor, default_relay);
}
- public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
- bool must_understand)
+ public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer,
+ bool mustUnderstand)
{
- return CreateHeader (name, ns, value, formatter, must_understand, default_actor, default_relay);
+ return CreateHeader (name, ns, value, serializer, mustUnderstand, default_actor, default_relay);
}
public static MessageHeader CreateHeader (string name, string ns, object value,
- bool must_understand, string actor, bool relay)
+ bool mustUnderstand, string actor, bool relay)
{
return CreateHeader (name, ns, value, new DataContractSerializer (value.GetType ()),
- must_understand, actor, relay);
+ mustUnderstand, actor, relay);
}
- public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
- bool must_understand, string actor)
+ public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer,
+ bool mustUnderstand, string actor)
{
- return CreateHeader (name, ns, value, formatter, must_understand, actor, default_relay);
+ return CreateHeader (name, ns, value, serializer, mustUnderstand, actor, default_relay);
}
- public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
- bool must_understand, string actor, bool relay)
+ public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer,
+ bool mustUnderstand, string actor, bool relay)
{
// FIXME: how to get IsReferenceParameter ?
- return new DefaultMessageHeader (name, ns, value, formatter, default_is_ref, must_understand, actor, relay);
+ return new DefaultMessageHeader (name, ns, value, serializer, default_is_ref, mustUnderstand, actor, relay);
}
- public virtual bool IsMessageVersionSupported (MessageVersion version)
+ public virtual bool IsMessageVersionSupported (MessageVersion messageVersion)
{
- if (version.Envelope == EnvelopeVersion.Soap12)
+ if (messageVersion.Envelope == EnvelopeVersion.Soap12)
if (Actor == EnvelopeVersion.Soap11.NextDestinationActorValue)
return false;
- if (version.Envelope == EnvelopeVersion.Soap11)
+ if (messageVersion.Envelope == EnvelopeVersion.Soap11)
if (Actor == EnvelopeVersion.Soap12.NextDestinationActorValue ||
Actor == EnvelopeVersion.Soap12UltimateReceiver)
return false;
return true;
}
- protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version);
+ protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion messageVersion);
- protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
+ protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
{
var dic = Constants.SoapDictionary;
XmlDictionaryString name, ns;
writer.WriteStartElement (prefix, name, ns);
else
writer.WriteStartElement (prefix, this.Name, this.Namespace);
- WriteHeaderAttributes (writer, version);
+ WriteHeaderAttributes (writer, messageVersion);
}
public override string ToString ()
return sb.ToString ();
}
- public void WriteHeader (XmlDictionaryWriter writer, MessageVersion version)
+ public void WriteHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
{
if (writer == null)
throw new ArgumentNullException ("writer is null.");
- if (version == null)
- throw new ArgumentNullException ("version is null.");
+ if (messageVersion == null)
+ throw new ArgumentNullException ("messageVersion is null.");
- if (version.Envelope == EnvelopeVersion.None)
+ if (messageVersion.Envelope == EnvelopeVersion.None)
return;
- WriteStartHeader (writer, version);
- WriteHeaderContents (writer, version);
+ WriteStartHeader (writer, messageVersion);
+ WriteHeaderContents (writer, messageVersion);
writer.WriteEndElement ();
}
- public void WriteHeader (XmlWriter writer, MessageVersion version)
+ public void WriteHeader (XmlWriter writer, MessageVersion messageVersion)
{
- WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), version);
+ WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), messageVersion);
}
- protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion version)
+ protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion messageVersion)
{
var dic = Constants.SoapDictionary;
if (Id != null)
writer.WriteAttributeString ("u", dic.Add ("Id"), dic.Add (Constants.WsuNamespace), Id);
if (!String.IsNullOrEmpty (Actor)) {
- if (version.Envelope == EnvelopeVersion.Soap11)
- writer.WriteAttributeString ("s", dic.Add ("actor"), dic.Add (version.Envelope.Namespace), Actor);
+ if (messageVersion.Envelope == EnvelopeVersion.Soap11)
+ writer.WriteAttributeString ("s", dic.Add ("actor"), dic.Add (messageVersion.Envelope.Namespace), Actor);
- if (version.Envelope == EnvelopeVersion.Soap12)
- writer.WriteAttributeString ("s", dic.Add ("role"), dic.Add (version.Envelope.Namespace), Actor);
+ if (messageVersion.Envelope == EnvelopeVersion.Soap12)
+ writer.WriteAttributeString ("s", dic.Add ("role"), dic.Add (messageVersion.Envelope.Namespace), Actor);
}
// mustUnderstand is the same across SOAP 1.1 and 1.2
if (MustUnderstand == true)
- writer.WriteAttributeString ("s", dic.Add ("mustUnderstand"), dic.Add (version.Envelope.Namespace), "1");
+ writer.WriteAttributeString ("s", dic.Add ("mustUnderstand"), dic.Add (messageVersion.Envelope.Namespace), "1");
// relay is only available on SOAP 1.2
- if (Relay == true && version.Envelope == EnvelopeVersion.Soap12)
- writer.WriteAttributeString ("s", dic.Add ("relay"), dic.Add (version.Envelope.Namespace), "true");
+ if (Relay == true && messageVersion.Envelope == EnvelopeVersion.Soap12)
+ writer.WriteAttributeString ("s", dic.Add ("relay"), dic.Add (messageVersion.Envelope.Namespace), "true");
}
- public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version)
+ public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion messageVersion)
{
- this.OnWriteHeaderContents (writer, version);
+ this.OnWriteHeaderContents (writer, messageVersion);
}
- public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
+ public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
{
- this.OnWriteStartHeader (writer, version);
+ this.OnWriteStartHeader (writer, messageVersion);
}
public override string Actor { get { return default_actor; }}
l.Add (header);
}
- public void CopyHeaderFrom (Message m, int index)
+ public void CopyHeaderFrom (Message message, int headerIndex)
{
- CopyHeaderFrom (m.Headers, index);
+ CopyHeaderFrom (message.Headers, headerIndex);
}
public void Clear ()
l.Clear ();
}
- public void CopyHeaderFrom (MessageHeaders headers, int index)
+ public void CopyHeaderFrom (MessageHeaders collection, int headerIndex)
{
- l.Add (headers [index]);
+ l.Add (collection [headerIndex]);
}
- public void CopyHeadersFrom (Message m)
+ public void CopyHeadersFrom (Message message)
{
- CopyHeadersFrom (m.Headers);
+ CopyHeadersFrom (message.Headers);
}
- public void CopyHeadersFrom (MessageHeaders headers)
+ public void CopyHeadersFrom (MessageHeaders collection)
{
- foreach (MessageHeaderInfo h in headers)
+ foreach (MessageHeaderInfo h in collection)
l.Add (h);
}
- public void CopyTo (MessageHeaderInfo [] dst, int index)
+ public void CopyTo (MessageHeaderInfo [] array, int index)
{
- l.CopyTo (dst, index);
+ l.CopyTo (array, index);
}
public int FindHeader (string name, string ns)
return GetHeader<T> (idx, serializer);
}
- public XmlDictionaryReader GetReaderAtHeader (int index)
+ public XmlDictionaryReader GetReaderAtHeader (int headerIndex)
{
- if (index >= l.Count)
- throw new ArgumentOutOfRangeException (String.Format ("Index is out of range. Current header count is {0}", index));
- MessageHeader item = (MessageHeader) l [index];
+ if (headerIndex >= l.Count)
+ throw new ArgumentOutOfRangeException (String.Format ("Index is out of range. Current header count is {0}", l.Count));
+ MessageHeader item = (MessageHeader) l [headerIndex];
XmlReader reader =
item is MessageHeader.XmlMessageHeader ?
throw new NotImplementedException ();
}
- public void Insert (int index, MessageHeader header)
+ public void Insert (int headerIndex, MessageHeader header)
{
- l.Insert (index, header);
+ l.Insert (headerIndex, header);
}
public void RemoveAll (string name, string ns)
l.RemoveAt (l.Count - 1);
}
- public void RemoveAt (int index)
+ public void RemoveAt (int headerIndex)
{
- l.RemoveAt (index);
+ l.RemoveAt (headerIndex);
}
IEnumerator IEnumerable.GetEnumerator ()
return ((IEnumerable) l).GetEnumerator ();
}
- public void WriteHeader (int index, XmlDictionaryWriter writer)
+ public void WriteHeader (int headerIndex, XmlDictionaryWriter writer)
{
if (version.Envelope == EnvelopeVersion.None)
return;
- WriteStartHeader (index, writer);
- WriteHeaderContents (index, writer);
+ WriteStartHeader (headerIndex, writer);
+ WriteHeaderContents (headerIndex, writer);
writer.WriteEndElement ();
}
- public void WriteHeader (int index, XmlWriter writer)
+ public void WriteHeader (int headerIndex, XmlWriter writer)
{
- WriteHeader (index, XmlDictionaryWriter.CreateDictionaryWriter (writer));
+ WriteHeader (headerIndex, XmlDictionaryWriter.CreateDictionaryWriter (writer));
}
- public void WriteHeaderContents (int index, XmlDictionaryWriter writer)
+ public void WriteHeaderContents (int headerIndex, XmlDictionaryWriter writer)
{
- if (index > l.Count)
- throw new ArgumentOutOfRangeException ("There is no header at position " + index + ".");
+ if (headerIndex > l.Count)
+ throw new ArgumentOutOfRangeException ("There is no header at position " + headerIndex + ".");
- MessageHeader h = l [index] as MessageHeader;
+ MessageHeader h = l [headerIndex] as MessageHeader;
h.WriteHeaderContents (writer, version);
}
- public void WriteHeaderContents (int index, XmlWriter writer)
+ public void WriteHeaderContents (int headerIndex, XmlWriter writer)
{
- WriteHeaderContents (index, XmlDictionaryWriter.CreateDictionaryWriter (writer));
+ WriteHeaderContents (headerIndex, XmlDictionaryWriter.CreateDictionaryWriter (writer));
}
- public void WriteStartHeader (int index, XmlDictionaryWriter writer)
+ public void WriteStartHeader (int headerIndex, XmlDictionaryWriter writer)
{
- if (index > l.Count)
- throw new ArgumentOutOfRangeException ("There is no header at position " + index + ".");
+ if (headerIndex > l.Count)
+ throw new ArgumentOutOfRangeException ("There is no header at position " + headerIndex + ".");
- MessageHeader h = l [index] as MessageHeader;
+ MessageHeader h = l [headerIndex] as MessageHeader;
h.WriteStartHeader (writer, version);
}
- public void WriteStartHeader (int index, XmlWriter writer)
+ public void WriteStartHeader (int headerIndex, XmlWriter writer)
{
- WriteStartHeader (index, XmlDictionaryWriter.CreateDictionaryWriter (writer));
+ WriteStartHeader (headerIndex, XmlDictionaryWriter.CreateDictionaryWriter (writer));
}
public string Action {
this.addressing = addressing;
}
- public static MessageVersion CreateVersion (EnvelopeVersion envelope_version)
+ public static MessageVersion CreateVersion (EnvelopeVersion envelopeVersion)
{
- return CreateVersion (envelope_version,
+ return CreateVersion (envelopeVersion,
AddressingVersion.WSAddressing10);
}
- public static MessageVersion CreateVersion (EnvelopeVersion envelope_version,
- AddressingVersion addressing_version)
+ public static MessageVersion CreateVersion (EnvelopeVersion envelopeVersion,
+ AddressingVersion addressingVersion)
{
- if (envelope_version == EnvelopeVersion.None && addressing_version == AddressingVersion.None)
+ if (envelopeVersion == EnvelopeVersion.None && addressingVersion == AddressingVersion.None)
return None;
- if (envelope_version == EnvelopeVersion.Soap11 && addressing_version == AddressingVersion.None)
+ if (envelopeVersion == EnvelopeVersion.Soap11 && addressingVersion == AddressingVersion.None)
return Soap11;
- if (envelope_version == EnvelopeVersion.Soap12 && addressing_version == AddressingVersion.WSAddressing10)
+ if (envelopeVersion == EnvelopeVersion.Soap12 && addressingVersion == AddressingVersion.WSAddressing10)
return Soap12WSAddressing10;
- if (envelope_version == EnvelopeVersion.Soap12 && addressing_version == AddressingVersion.None)
+ if (envelopeVersion == EnvelopeVersion.Soap12 && addressingVersion == AddressingVersion.None)
return Soap12;
- if (envelope_version == EnvelopeVersion.Soap11 && addressing_version == AddressingVersion.WSAddressing10)
+ if (envelopeVersion == EnvelopeVersion.Soap11 && addressingVersion == AddressingVersion.WSAddressing10)
return Soap11WSAddressing10;
- if (envelope_version == EnvelopeVersion.Soap11 && addressing_version == AddressingVersion.WSAddressingAugust2004)
+ if (envelopeVersion == EnvelopeVersion.Soap11 && addressingVersion == AddressingVersion.WSAddressingAugust2004)
return Soap11WSAddressingAugust2004;
- if (envelope_version == EnvelopeVersion.Soap12 && addressing_version == AddressingVersion.WSAddressingAugust2004)
+ if (envelopeVersion == EnvelopeVersion.Soap12 && addressingVersion == AddressingVersion.WSAddressingAugust2004)
return Soap12WSAddressingAugust2004;
- throw new ArgumentException (string.Format ("EnvelopeVersion {0} cannot be used with AddressingVersion {1}", envelope_version, addressing_version));
+ throw new ArgumentException (string.Format ("EnvelopeVersion {0} cannot be used with AddressingVersion {1}", envelopeVersion, addressingVersion));
}
- public override bool Equals (object value)
+ public override bool Equals (object obj)
{
- MessageVersion other = value as MessageVersion;
+ MessageVersion other = obj as MessageVersion;
if (other == null)
return false;
#endif
public static SecurityBindingElement
- CreateSecureConversationBindingElement (SecurityBindingElement binding)
+ CreateSecureConversationBindingElement (SecurityBindingElement bootstrapSecurity)
{
- return CreateSecureConversationBindingElement (binding, false);
+ return CreateSecureConversationBindingElement (bootstrapSecurity, false);
}
public static SecurityBindingElement
CreateSecureConversationBindingElement (
- SecurityBindingElement binding, bool requireCancellation)
+ SecurityBindingElement bootstrapSecurity, bool requireCancellation)
{
- return CreateSecureConversationBindingElement (binding, requireCancellation, null);
+ return CreateSecureConversationBindingElement (bootstrapSecurity, requireCancellation, null);
}
public static SecurityBindingElement
CreateSecureConversationBindingElement (
- SecurityBindingElement binding, bool requireCancellation,
- ChannelProtectionRequirements protectionRequirements)
+ SecurityBindingElement bootstrapSecurity, bool requireCancellation,
+ ChannelProtectionRequirements bootstrapProtectionRequirements)
{
#if !MOBILE && !XAMMAC_4_5
SymmetricSecurityBindingElement be =
new SymmetricSecurityBindingElement ();
be.ProtectionTokenParameters =
new SecureConversationSecurityTokenParameters (
- binding, requireCancellation, protectionRequirements);
+ bootstrapSecurity, requireCancellation, bootstrapProtectionRequirements);
return be;
#else
throw new NotImplementedException ();
}
protected TcpTransportBindingElement (
- TcpTransportBindingElement other)
- : base (other)
+ TcpTransportBindingElement elementToBeCloned)
+ : base (elementToBeCloned)
{
- listen_backlog = other.listen_backlog;
- port_sharing_enabled = other.port_sharing_enabled;
- pool.CopyPropertiesFrom (other.pool);
+ listen_backlog = elementToBeCloned.listen_backlog;
+ port_sharing_enabled = elementToBeCloned.port_sharing_enabled;
+ pool.CopyPropertiesFrom (elementToBeCloned.pool);
}
public TcpConnectionPoolSettings ConnectionPoolSettings {
}
protected TransportBindingElement (
- TransportBindingElement other)
- : base (other)
+ TransportBindingElement elementToBeCloned)
+ : base (elementToBeCloned)
{
- manual_addressing = other.manual_addressing;
- max_buffer_pool_size = other.max_buffer_pool_size;
- max_recv_message_size = other.max_recv_message_size;
+ manual_addressing = elementToBeCloned.manual_addressing;
+ max_buffer_pool_size = elementToBeCloned.max_buffer_pool_size;
+ max_recv_message_size = elementToBeCloned.max_recv_message_size;
}
public virtual bool ManualAddressing {
}
[MonoTODO]
- protected ClientCredentials (ClientCredentials source)
+ protected ClientCredentials (ClientCredentials other)
{
- userpass = source.userpass.Clone ();
- digest = source.digest.Clone ();
- initiator = source.initiator.Clone ();
- recipient = source.recipient.Clone ();
- windows = source.windows.Clone ();
+ userpass = other.userpass.Clone ();
+ digest = other.digest.Clone ();
+ initiator = other.initiator.Clone ();
+ recipient = other.recipient.Clone ();
+ windows = other.windows.Clone ();
#if !MOBILE
- issued_token = source.issued_token.Clone ();
- peer = source.peer.Clone ();
- support_interactive = source.support_interactive;
+ issued_token = other.issued_token.Clone ();
+ peer = other.peer.Clone ();
+ support_interactive = other.support_interactive;
#endif
}
[MonoTODO]
public virtual void ApplyClientBehavior (
- ServiceEndpoint endpoint, ClientRuntime behavior)
+ ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
{
- if (endpoint == null)
- throw new ArgumentNullException ("endpoint");
+ if (serviceEndpoint == null)
+ throw new ArgumentNullException ("serviceEndpoint");
if (behavior == null)
throw new ArgumentNullException ("behavior");
public interface IContractBehavior
{
void AddBindingParameters (
- ContractDescription description,
+ ContractDescription contractDescription,
ServiceEndpoint endpoint,
- BindingParameterCollection parameters);
+ BindingParameterCollection bindingParameters);
void ApplyClientBehavior (
- ContractDescription description,
+ ContractDescription contractDescription,
ServiceEndpoint endpoint,
- ClientRuntime proxy);
+ ClientRuntime clientRuntime);
void ApplyDispatchBehavior (
- ContractDescription description,
+ ContractDescription contractDescription,
ServiceEndpoint endpoint,
- DispatchRuntime dispatch);
+ DispatchRuntime dispatchRuntime);
void Validate (
- ContractDescription description,
+ ContractDescription contractDescription,
ServiceEndpoint endpoint);
}
}
public interface IEndpointBehavior
{
void AddBindingParameters (ServiceEndpoint endpoint,
- BindingParameterCollection parameters);
- void ApplyDispatchBehavior (ServiceEndpoint serviceEndpoint,
- EndpointDispatcher dispatcher);
- void ApplyClientBehavior (ServiceEndpoint serviceEndpoint,
- ClientRuntime behavior);
- void Validate (ServiceEndpoint serviceEndpoint);
+ BindingParameterCollection bindingParameters);
+ void ApplyDispatchBehavior (ServiceEndpoint endpoint,
+ EndpointDispatcher endpointDispatcher);
+ void ApplyClientBehavior (ServiceEndpoint endpoint,
+ ClientRuntime clientRuntime);
+ void Validate (ServiceEndpoint endpoint);
}
}
public interface IOperationBehavior
{
void AddBindingParameters (
- OperationDescription description,
- BindingParameterCollection parameters);
+ OperationDescription operationDescription,
+ BindingParameterCollection bindingParameters);
void ApplyDispatchBehavior (
- OperationDescription description,
- DispatchOperation dispatch);
+ OperationDescription operationDescription,
+ DispatchOperation dispatchOperation);
void ApplyClientBehavior (
- OperationDescription description,
- ClientOperation proxy);
+ OperationDescription operationDescription,
+ ClientOperation clientOperation);
void Validate (
- OperationDescription description);
+ OperationDescription operationDescription);
}
}
{
public interface IClientMessageFormatter
{
- object DeserializeReply (Message message, object [] paremeters);
- Message SerializeRequest (MessageVersion version, object [] inputs);
+ object DeserializeReply (Message message, object [] parameters);
+ Message SerializeRequest (MessageVersion messageVersion, object [] parameters);
}
}
{
public interface IClientMessageInspector
{
- void AfterReceiveReply (ref Message message, object correlationState);
- object BeforeSendRequest (ref Message message, IClientChannel channel);
+ void AfterReceiveReply (ref Message reply, object correlationState);
+ object BeforeSendRequest (ref Message request, IClientChannel channel);
}
}
}
public SecureConversationSecurityTokenParameters (
- SecurityBindingElement element)
- : this (element, true)
+ SecurityBindingElement bootstrapSecurityBindingElement)
+ : this (bootstrapSecurityBindingElement, true)
{
}
public SecureConversationSecurityTokenParameters (
- SecurityBindingElement element,
+ SecurityBindingElement bootstrapSecurityBindingElement,
bool requireCancellation)
- : this (element, requireCancellation, null)
+ : this (bootstrapSecurityBindingElement, requireCancellation, null)
{
}
#if !MOBILE && !XAMMAC_4_5
public SecureConversationSecurityTokenParameters (
- SecurityBindingElement element,
+ SecurityBindingElement bootstrapSecurityBindingElement,
bool requireCancellation,
- ChannelProtectionRequirements requirements)
+ ChannelProtectionRequirements bootstrapProtectionRequirements)
{
- this.element = element;
+ this.element = bootstrapSecurityBindingElement;
this.cancellable = requireCancellation;
- if (requirements == null)
+ if (bootstrapProtectionRequirements == null)
this.requirements = new ChannelProtectionRequirements (default_channel_protection_requirements);
else
- this.requirements = new ChannelProtectionRequirements (requirements);
+ this.requirements = new ChannelProtectionRequirements (bootstrapProtectionRequirements);
}
#else
internal SecureConversationSecurityTokenParameters (
public class ActionNotSupportedException : CommunicationException
{
public ActionNotSupportedException () : base () {}
- public ActionNotSupportedException (string msg) : base (msg) {}
- public ActionNotSupportedException (string msg, Exception inner) : base (msg, inner) {}
+ public ActionNotSupportedException (string message) : base (message) {}
+ public ActionNotSupportedException (string message, Exception innerException) : base (message, innerException) {}
protected ActionNotSupportedException (SerializationInfo info, StreamingContext context) :
base (info, context) {}
}
get { return Endpoint.Binding.OpenTimeout; }
}
- protected virtual void ApplyConfiguration (string endpointConfig)
+ protected virtual void ApplyConfiguration (string configurationName)
{
- if (endpointConfig == null)
+ if (configurationName == null)
return;
#if MOBILE || XAMMAC_4_5
var cfg = new SilverlightClientConfigLoader ().Load (XmlReader.Create ("ServiceReferences.ClientConfig"));
SilverlightClientConfigLoader.ServiceEndpointConfiguration se = null;
- if (endpointConfig == "*")
+ if (configurationName == "*")
se = cfg.GetServiceEndpointConfiguration (Endpoint.Contract.Name);
if (se == null)
- se = cfg.GetServiceEndpointConfiguration (endpointConfig);
+ se = cfg.GetServiceEndpointConfiguration (configurationName);
if (se.Binding != null && Endpoint.Binding == null)
Endpoint.Binding = se.Binding;
else // ignore it
- Console.WriteLine ("WARNING: Configured binding not found in configuration {0}", endpointConfig);
+ Console.WriteLine ("WARNING: Configured binding not found in configuration {0}", configurationName);
if (se.Address != null && Endpoint.Address == null)
Endpoint.Address = se.Address;
else // ignore it
- Console.WriteLine ("WARNING: Configured endpoint address not found in configuration {0}", endpointConfig);
+ Console.WriteLine ("WARNING: Configured endpoint address not found in configuration {0}", configurationName);
} catch (Exception) {
// ignore it.
- Console.WriteLine ("WARNING: failed to load endpoint configuration for {0}", endpointConfig);
+ Console.WriteLine ("WARNING: failed to load endpoint configuration for {0}", configurationName);
}
#else
ChannelEndpointElement endpoint = null;
foreach (ChannelEndpointElement el in client.Endpoints) {
- if (el.Contract == contractName && (endpointConfig == el.Name || endpointConfig == "*")) {
+ if (el.Contract == contractName && (configurationName == el.Name || configurationName == "*")) {
if (endpoint != null)
throw new InvalidOperationException (String.Format ("More then one endpoint matching contract {0} was found.", contractName));
endpoint = el;
}
if (endpoint == null)
- throw new InvalidOperationException (String.Format ("Client endpoint configuration '{0}' was not found in {1} endpoints.", endpointConfig, client.Endpoints.Count));
+ throw new InvalidOperationException (String.Format ("Client endpoint configuration '{0}' was not found in {1} endpoints.", configurationName, client.Endpoints.Count));
var binding = String.IsNullOrEmpty (endpoint.Binding) ? null : ConfigUtil.CreateBinding (endpoint.Binding, endpoint.BindingConfiguration);
var contractType = ConfigUtil.GetTypeFromConfigString (endpoint.Contract, NamedConfigCategory.Contract);
}
protected void InitializeEndpoint (
- string endpointConfigurationName,
+ string configurationName,
EndpointAddress remoteAddress)
{
InitializeEndpoint (CreateDescription ());
if (remoteAddress != null)
service_endpoint.Address = remoteAddress;
- ApplyConfiguration (endpointConfigurationName);
+ ApplyConfiguration (configurationName);
}
protected void InitializeEndpoint (Binding binding,
- EndpointAddress remoteAddress)
+ EndpointAddress address)
{
InitializeEndpoint (CreateDescription ());
if (binding != null)
service_endpoint.Binding = binding;
- if (remoteAddress != null)
- service_endpoint.Address = remoteAddress;
+ if (address != null)
+ service_endpoint.Address = address;
}
protected void InitializeEndpoint (ServiceEndpoint endpoint)
{
}
- protected ChannelFactory (Type type)
+ protected ChannelFactory (Type channelType)
{
- if (type == null)
- throw new ArgumentNullException ("type");
- if (!type.IsInterface)
- throw new InvalidOperationException ("The type argument to the generic ChannelFactory constructor must be an interface type.");
+ if (channelType == null)
+ throw new ArgumentNullException ("channelType");
+ if (!channelType.IsInterface)
+ throw new InvalidOperationException ("The channelType argument to the generic ChannelFactory constructor must be an interface type.");
InitializeEndpoint (CreateDescription ());
}
public class CommunicationException : SystemException
{
public CommunicationException () : base () {}
- public CommunicationException (string msg) : base (msg) {}
- public CommunicationException (string msg, Exception inner) : base (msg, inner) {}
+ public CommunicationException (string message) : base (message) {}
+ public CommunicationException (string message, Exception innerException) : base (message, innerException) {}
protected CommunicationException (SerializationInfo info, StreamingContext context)
: base (info, context) {}
}
public class CommunicationObjectAbortedException : CommunicationException
{
public CommunicationObjectAbortedException () : base () {}
- public CommunicationObjectAbortedException (string msg) : base (msg) {}
- public CommunicationObjectAbortedException (string msg, Exception inner)
- : base (msg, inner) {}
+ public CommunicationObjectAbortedException (string message) : base (message) {}
+ public CommunicationObjectAbortedException (string message, Exception innerException)
+ : base (message, innerException) {}
protected CommunicationObjectAbortedException (SerializationInfo info,
StreamingContext context)
: base (info, context) {}
public class CommunicationObjectFaultedException : CommunicationException
{
public CommunicationObjectFaultedException () : base () {}
- public CommunicationObjectFaultedException (string msg) : base (msg) {}
- public CommunicationObjectFaultedException (string msg, Exception inner)
- : base (msg, inner) {}
+ public CommunicationObjectFaultedException (string message) : base (message) {}
+ public CommunicationObjectFaultedException (string message, Exception innerException)
+ : base (message, innerException) {}
protected CommunicationObjectFaultedException (SerializationInfo info, StreamingContext context)
: base (info, context) {}
}
Initialize (identity);
}
- public DnsEndpointIdentity (string dns)
- : this (Claim.CreateDnsClaim (dns))
+ public DnsEndpointIdentity (string dnsName)
+ : this (Claim.CreateDnsClaim (dnsName))
{
}
#else
- public DnsEndpointIdentity (string dns)
+ public DnsEndpointIdentity (string dnsName)
{
throw new NotImplementedException ();
}
{
public class DuplexClientBase<TChannel> : ClientBase<TChannel> where TChannel : class
{
- protected DuplexClientBase (object instance)
- : this (new InstanceContext (instance), (Binding) null, null)
+ protected DuplexClientBase (object callbackInstance)
+ : this (new InstanceContext (callbackInstance), (Binding) null, null)
{
}
- protected DuplexClientBase (object instance,
- Binding binding, EndpointAddress address)
- : this (new InstanceContext (instance), binding, address)
+ protected DuplexClientBase (object callbackInstance,
+ Binding binding, EndpointAddress remoteAddress)
+ : this (new InstanceContext (callbackInstance), binding, remoteAddress)
{
}
- protected DuplexClientBase (object instance,
- string configurationName)
- : this (new InstanceContext (instance), configurationName)
+ protected DuplexClientBase (object callbackInstance,
+ string endpointConfigurationName)
+ : this (new InstanceContext (callbackInstance), endpointConfigurationName)
{
}
- protected DuplexClientBase (object instance,
- string bindingConfigurationName, EndpointAddress address)
- : this (new InstanceContext (instance), bindingConfigurationName, address)
+ protected DuplexClientBase (object callbackInstance,
+ string bindingConfigurationName, EndpointAddress remoteAddress)
+ : this (new InstanceContext (callbackInstance), bindingConfigurationName, remoteAddress)
{
}
- protected DuplexClientBase (object instance,
+ protected DuplexClientBase (object callbackInstance,
string endpointConfigurationName, string remoteAddress)
- : this (new InstanceContext (instance), endpointConfigurationName, remoteAddress)
+ : this (new InstanceContext (callbackInstance), endpointConfigurationName, remoteAddress)
{
}
- protected DuplexClientBase (InstanceContext instance)
- : base (instance)
+ protected DuplexClientBase (InstanceContext callbackInstance)
+ : base (callbackInstance)
{
}
- protected DuplexClientBase (InstanceContext instance,
- Binding binding, EndpointAddress address)
- : base (instance, binding, address)
+ protected DuplexClientBase (InstanceContext callbackInstance,
+ Binding binding, EndpointAddress remoteAddress)
+ : base (callbackInstance, binding, remoteAddress)
{
}
- protected DuplexClientBase (InstanceContext instance,
- string configurationName)
- : base (instance, configurationName)
+ protected DuplexClientBase (InstanceContext callbackInstance,
+ string endpointConfigurationName)
+ : base (callbackInstance, endpointConfigurationName)
{
}
- protected DuplexClientBase (InstanceContext instance,
+ protected DuplexClientBase (InstanceContext callbackInstance,
string endpointConfigurationName, string remoteAddress)
- : base (instance, endpointConfigurationName, remoteAddress)
+ : base (callbackInstance, endpointConfigurationName, remoteAddress)
{
}
- protected DuplexClientBase (InstanceContext instance,
- string configurationName, EndpointAddress address)
- : base (instance, configurationName, address)
+ protected DuplexClientBase (InstanceContext callbackInstance,
+ string endpointConfigurationName, EndpointAddress address)
+ : base (callbackInstance, endpointConfigurationName, address)
{
}
- protected DuplexClientBase (object instance, ServiceEndpoint endpoint)
- : this (new InstanceContext (instance), endpoint)
+ protected DuplexClientBase (object callbackInstance, ServiceEndpoint endpoint)
+ : this (new InstanceContext (callbackInstance), endpoint)
{
}
- protected DuplexClientBase (InstanceContext instance, ServiceEndpoint endpoint)
- : base (instance, endpoint)
+ protected DuplexClientBase (InstanceContext callbackInstance, ServiceEndpoint endpoint)
+ : base (callbackInstance, endpoint)
{
}
{
}
- public EndpointAddress (Uri uri, params AddressHeader [] headers)
- : this (uri, null, new AddressHeaderCollection (headers), null, null) {}
+ public EndpointAddress (Uri uri, params AddressHeader [] addressHeaders)
+ : this (uri, null, new AddressHeaderCollection (addressHeaders), null, null) {}
- public EndpointAddress (Uri uri, EndpointIdentity identity, params AddressHeader [] headers)
- : this (uri, identity, new AddressHeaderCollection (headers), null, null) {}
+ public EndpointAddress (Uri uri, EndpointIdentity identity, params AddressHeader [] addressHeaders)
+ : this (uri, identity, new AddressHeaderCollection (addressHeaders), null, null) {}
public EndpointAddress (Uri uri, EndpointIdentity identity, AddressHeaderCollection headers)
: this (uri, identity, headers, null, null) {}
public class EndpointNotFoundException : CommunicationException
{
public EndpointNotFoundException () : base () {}
- public EndpointNotFoundException (string msg) : base (msg) {}
- public EndpointNotFoundException (string msg, Exception inner) : base (msg, inner) {}
+ public EndpointNotFoundException (string message) : base (message) {}
+ public EndpointNotFoundException (string message, Exception innerException) : base (message, innerException) {}
protected EndpointNotFoundException (SerializationInfo info, StreamingContext context) :
base (info, context) {}
}
{
}
- public FaultCode (string name, FaultCode subcode)
- : this (name, String.Empty, subcode)
+ public FaultCode (string name, FaultCode subCode)
+ : this (name, String.Empty, subCode)
{
}
- public FaultCode (string name, string ns, FaultCode subcode)
+ public FaultCode (string name, string ns, FaultCode subCode)
{
this.name = name;
this.ns = ns;
- this.subcode = subcode;
+ this.subcode = subCode;
}
public bool IsPredefinedFault {
get { return subcode; }
}
- public static FaultCode CreateReceiverFaultCode (FaultCode subcode)
+ public static FaultCode CreateReceiverFaultCode (FaultCode subCode)
{
- return new FaultCode ("Receiver", subcode);
+ return new FaultCode ("Receiver", subCode);
}
public static FaultCode CreateReceiverFaultCode (string name, string ns)
return CreateReceiverFaultCode (new FaultCode (name, ns));
}
- public static FaultCode CreateSenderFaultCode (FaultCode subcode)
+ public static FaultCode CreateSenderFaultCode (FaultCode subCode)
{
- return new FaultCode ("Sender", subcode);
+ return new FaultCode ("Sender", subCode);
}
public static FaultCode CreateSenderFaultCode (string name, string ns)
}
[MonoTODO]
- public static FaultException CreateFault (MessageFault fault, params Type [] details)
+ public static FaultException CreateFault (MessageFault messageFault, params Type [] faultDetailTypes)
{
throw new NotImplementedException ();
}
public class InvalidMessageContractException : SystemException
{
public InvalidMessageContractException () : base () {}
- public InvalidMessageContractException (string msg) : base (msg) {}
- public InvalidMessageContractException (string msg, Exception inner) : base (msg, inner) {}
+ public InvalidMessageContractException (string message) : base (message) {}
+ public InvalidMessageContractException (string message, Exception innerException) : base (message, innerException) {}
protected InvalidMessageContractException (SerializationInfo info, StreamingContext context) :
base (info, context) {}
}
public class MessageHeaderException : ProtocolException
{
public MessageHeaderException () : this ("Message header exception") {}
- public MessageHeaderException (string msg) : this (msg, null) {}
- public MessageHeaderException (string msg, Exception inner) : base (msg, inner) {}
+ public MessageHeaderException (string message) : this (message, null) {}
+ public MessageHeaderException (string message, Exception innerException) : base (message, innerException) {}
protected MessageHeaderException (SerializationInfo info, StreamingContext context) :
base (info, context)
{
{
}
- public MessageHeader (T content, bool must_understand, string actor, bool relay)
+ public MessageHeader (T content, bool mustUnderstand, string actor, bool relay)
{
this.content = content;
- this.must_understand = must_understand;
+ this.must_understand = mustUnderstand;
this.actor = actor;
this.relay = relay;
}
public class ProtocolException : CommunicationException
{
public ProtocolException () : base () {}
- public ProtocolException (string msg) : base (msg) {}
- public ProtocolException (string msg, Exception inner)
- : base (msg, inner) {}
+ public ProtocolException (string message) : base (message) {}
+ public ProtocolException (string message, Exception innerException)
+ : base (message, innerException) {}
protected ProtocolException (SerializationInfo info,
StreamingContext context)
: base (info, context) {}
public class QuotaExceededException : SystemException
{
public QuotaExceededException () : base () {}
- public QuotaExceededException (string msg) : base (msg) {}
- public QuotaExceededException (string msg, Exception inner)
- : base (msg, inner) {}
+ public QuotaExceededException (string message) : base (message) {}
+ public QuotaExceededException (string message, Exception innerException)
+ : base (message, innerException) {}
protected QuotaExceededException (SerializationInfo info,
StreamingContext context)
: base (info, context) {}
public class ServerTooBusyException : CommunicationException
{
public ServerTooBusyException () : base () {}
- public ServerTooBusyException (string msg) : base (msg) {}
- public ServerTooBusyException (string msg, Exception inner)
- : base (msg, inner) {}
+ public ServerTooBusyException (string message) : base (message) {}
+ public ServerTooBusyException (string message, Exception innerException)
+ : base (message, innerException) {}
protected ServerTooBusyException (SerializationInfo info,
StreamingContext context)
: base (info, context) {}
public class ServiceActivationException : CommunicationException
{
public ServiceActivationException () : base () {}
- public ServiceActivationException (string msg) : base (msg) {}
- public ServiceActivationException (string msg, Exception inner)
- : base (msg, inner) {}
+ public ServiceActivationException (string message) : base (message) {}
+ public ServiceActivationException (string message, Exception innerException)
+ : base (message, innerException) {}
protected ServiceActivationException (SerializationInfo info,
StreamingContext context)
: base (info, context) {}
Initialize (identity);
}
- public SpnEndpointIdentity (string spn)
- : this (Claim.CreateSpnClaim (spn))
+ public SpnEndpointIdentity (string spnName)
+ : this (Claim.CreateSpnClaim (spnName))
{
}
#else
- public SpnEndpointIdentity (string spn)
+ public SpnEndpointIdentity (string spnName)
{
throw new NotImplementedException ();
}
Initialize (identity);
}
- public UpnEndpointIdentity (string upn)
- : this (Claim.CreateUpnClaim (upn))
+ public UpnEndpointIdentity (string upnName)
+ : this (Claim.CreateUpnClaim (upnName))
{
}
#else
- public UpnEndpointIdentity (string upn)
+ public UpnEndpointIdentity (string upnName)
{
throw new NotImplementedException ();
}
AuthenticationSchemes.Ntlm, label);
}
-#if NET_4_5
[Test]
public virtual void BasicHttps ()
{
WSMessageEncoding.Text, HttpClientCredentialType.None,
AuthenticationSchemes.Anonymous, label);
}
-#endif
[Test]
public virtual void NetTcp ()
return exporter.GetGeneratedMetadata ();
}
-#if NET_4_5
[MetadataSample]
public static MetadataSet BasicHttps ()
{
return exporter.GetGeneratedMetadata ();
}
-#endif
[MetadataSample]
public static MetadataSet NetTcp ()
for (int i = 0; i < array.Length; ++i)
Assert.IsTrue (block.Post (i), "Not accepted");
- Thread.Sleep (300);
+ Thread.Sleep (600);
block.LinkTo (action);
- Thread.Sleep (100);
+ Thread.Sleep (300);
CollectionAssert.AreEqual (new[] { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 }, array);
}
}
}
-#if NET_4_5
[Test]
public void Protect ()
{
MachineKey.Unprotect (encryptedBytes, oneUsage),
"Single purpose working when multiple supplied");
}
-#endif
}
}
-#if NET_4_5
using System.ComponentModel.DataAnnotations;
using System.Linq;
}
}
}
-#endif
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading.Tasks;
}
}
-#endif
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.IO;
}
}
-#endif
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
using System.Xml;\r
using System.Xml.Schema;\r
using System.Xml.XPath;\r
-#if NET_4_5\r
using System.Threading;\r
using System.Threading.Tasks;\r
-#endif\r
\r
using NUnit.Framework;\r
\r
Assert.AreEqual ((UInt64) 1, xr.ReadContentAs (typeof (UInt64), null), "#8");\r
}\r
\r
-#if NET_4_5\r
[Test]\r
[ExpectedException(typeof(InvalidOperationException))]\r
public void MustSetAsyncFlag ()\r
if (task.Result != null)\r
throw task.Result;\r
}\r
-#endif\r
}\r
}\r
Assert.AreEqual ("urn:foo", r.BaseURI);
}
-#if NET_4_5
[Test]
[ExpectedException (typeof (XmlException))]
public void ReadonlyAsync ()
var r2 = XmlReader.Create (r, c);
Assert.IsTrue (r2.Settings.Async);
}
-#endif
}
}
Assert.IsTrue (u2.IsAbsoluteUri, "null,absolute/file");
}
-#if NET_4_5
class AsyncXmlResolver : XmlResolver
{
public override object GetEntity (Uri absoluteUri, string role, Type ofObjectToReturn)
var uri = new Uri ("http://www.mono-project.com");
ar.GetEntityAsync (uri, null, typeof(string));
}
-#endif
}
}
Assert.IsTrue (site, "Site-2");
}
-#if NET_4_5
[Test]
[Category("Async")]
public void TestAsync ()
Assert.That (task.Wait (3000));
Assert.IsInstanceOfType (typeof (Stream), task.Result);
}
-#endif
}
}
using System.IO;\r
using System.Xml;\r
using NUnit.Framework;\r
-#if NET_4_5\r
using System.Reflection;\r
-#endif\r
\r
namespace MonoTests.System.Xml\r
{\r
Assert.AreEqual ("view:Standard.xslt", uri.AbsoluteUri, "#2");\r
}\r
\r
-#if NET_4_5\r
[Test]\r
public void TestAsync ()\r
{\r
Assert.IsTrue (ex is XmlException);\r
}\r
}\r
-#endif\r
}\r
}\r
Assert.AreEqual (false, s.NewLineOnAttributes);
Assert.AreEqual (false, s.OmitXmlDeclaration);
Assert.AreEqual (NewLineHandling.Replace, s.NewLineHandling);
-#if NET_4_5
Assert.IsFalse (s.Async);
-#endif
}
[Test]
Assert.AreEqual (xml, sw.ToString ());
}
-#if NET_4_5
[Test]
[ExpectedException (typeof (XmlException))]
public void ReadonlyAsync ()
var w2 = XmlWriter.Create (w, c);
Assert.IsTrue (w2.Settings.Async);
}
-#endif
}
}
public XElement Content;
}
-#if NET_4_5
[Test]
// Bug #12571
public void DeserializeXElement ()
var xe = (SerializableClass)res;
Assert.AreEqual (xe.Content.ToString (), "<Data />", "#3");
}
-#endif
[Test] // Bug #20151
public void XElementFromArrayWithNullValuesAsObject ()
bool disposed;
DeflateStreamNative native;
- public DeflateStream (Stream compressedStream, CompressionMode mode) :
- this (compressedStream, mode, false, false)
+ public DeflateStream (Stream stream, CompressionMode mode) :
+ this (stream, mode, false, false)
{
}
- public DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen) :
- this (compressedStream, mode, leaveOpen, false)
+ public DeflateStream (Stream stream, CompressionMode mode, bool leaveOpen) :
+ this (stream, mode, leaveOpen, false)
{
}
}
}
- public override int Read (byte[] dest, int dest_offset, int count)
+ public override int Read (byte[] array, int offset, int count)
{
if (disposed)
throw new ObjectDisposedException (GetType ().FullName);
- if (dest == null)
+ if (array == null)
throw new ArgumentNullException ("Destination array is null.");
if (!CanRead)
throw new InvalidOperationException ("Stream does not support reading.");
- int len = dest.Length;
- if (dest_offset < 0 || count < 0)
+ int len = array.Length;
+ if (offset < 0 || count < 0)
throw new ArgumentException ("Dest or count is negative.");
- if (dest_offset > len)
+ if (offset > len)
throw new ArgumentException ("destination offset is beyond array size");
- if ((dest_offset + count) > len)
+ if ((offset + count) > len)
throw new ArgumentException ("Reading would overrun buffer");
- return ReadInternal (dest, dest_offset, count);
+ return ReadInternal (array, offset, count);
}
unsafe void WriteInternal (byte[] array, int offset, int count)
}
}
- public override void Write (byte[] src, int src_offset, int count)
+ public override void Write (byte[] array, int offset, int count)
{
if (disposed)
throw new ObjectDisposedException (GetType ().FullName);
- if (src == null)
- throw new ArgumentNullException ("src");
+ if (array == null)
+ throw new ArgumentNullException ("array");
- if (src_offset < 0)
- throw new ArgumentOutOfRangeException ("src_offset");
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset");
if (count < 0)
throw new ArgumentOutOfRangeException ("count");
if (!CanWrite)
throw new NotSupportedException ("Stream does not support writing");
- if (src_offset > src.Length - count)
+ if (offset > array.Length - count)
throw new ArgumentException ("Buffer too small. count/offset wrong.");
- WriteInternal (src, src_offset, count);
+ WriteInternal (array, offset, count);
}
public override void Flush ()
base.Dispose (disposing);
}
- public override int Read (byte[] dest, int dest_offset, int count)
+ public override int Read (byte[] array, int offset, int count)
{
if (deflateStream == null)
throw new ObjectDisposedException (GetType ().FullName);
- return deflateStream.Read(dest, dest_offset, count);
+ return deflateStream.Read(array, offset, count);
}
- public override void Write (byte[] src, int src_offset, int count)
+ public override void Write (byte[] array, int offset, int count)
{
if (deflateStream == null)
throw new ObjectDisposedException (GetType ().FullName);
- deflateStream.Write (src, src_offset, count);
+ deflateStream.Write (array, offset, count);
}
public override void Flush()
* effects on Linux, as the socket option is kludged by
* turning on or off PMTU discovery... */
this.DontFragment = false;
+ this.NoDelay = false;
+ } else if (address_family == AddressFamily.InterNetworkV6) {
+ this.DualMode = true;
}
/* Microsoft sets these to 8192, but we are going to keep them
#region Poll
- public bool Poll (int time_us, SelectMode mode)
+ public bool Poll (int microSeconds, SelectMode mode)
{
ThrowIfDisposedAndClosed ();
throw new NotSupportedException ("'mode' parameter is not valid.");
int error;
- bool result = Poll_internal (safe_handle, mode, time_us, out error);
+ bool result = Poll_internal (safe_handle, mode, microSeconds, out error);
if (error != 0)
throw new SocketException (error);
#region Bind
- public void Bind (EndPoint local_end)
+ public void Bind (EndPoint localEP)
{
ThrowIfDisposedAndClosed ();
- if (local_end == null)
- throw new ArgumentNullException("local_end");
+ if (localEP == null)
+ throw new ArgumentNullException("localEP");
- var ipEndPoint = local_end as IPEndPoint;
+ var ipEndPoint = localEP as IPEndPoint;
if (ipEndPoint != null) {
- local_end = RemapIPEndPoint (ipEndPoint);
+ localEP = RemapIPEndPoint (ipEndPoint);
}
int error;
- Bind_internal (safe_handle, local_end.Serialize(), out error);
+ Bind_internal (safe_handle, localEP.Serialize(), out error);
if (error != 0)
throw new SocketException (error);
if (error == 0)
is_bound = true;
- seed_endpoint = local_end;
+ seed_endpoint = localEP;
}
private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
return Receive (buffer, SocketFlags.None);
}
- public int Receive (byte [] buffer, SocketFlags flags)
+ public int Receive (byte [] buffer, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
SocketError error;
- int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
+ int ret = Receive_nochecks (buffer, 0, buffer.Length, socketFlags, out error);
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
return ret;
}
- public int Receive (byte [] buffer, int size, SocketFlags flags)
+ public int Receive (byte [] buffer, int size, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, size);
SocketError error;
- int ret = Receive_nochecks (buffer, 0, size, flags, out error);
+ int ret = Receive_nochecks (buffer, 0, size, socketFlags, out error);
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
return ret;
}
- public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
+ public int Receive (byte [] buffer, int offset, int size, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, offset, size);
SocketError error;
- int ret = Receive_nochecks (buffer, offset, size, flags, out error);
+ int ret = Receive_nochecks (buffer, offset, size, socketFlags, out error);
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
return ret;
}
- public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
+ public int Receive (byte [] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, offset, size);
- return Receive_nochecks (buffer, offset, size, flags, out error);
+ return Receive_nochecks (buffer, offset, size, socketFlags, out errorCode);
}
public int Receive (IList<ArraySegment<byte>> buffers)
return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
}
- public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
+ public int ReceiveFrom (byte [] buffer, SocketFlags socketFlags, ref EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- return ReceiveFrom (buffer, 0, buffer.Length, flags, ref remoteEP);
+ return ReceiveFrom (buffer, 0, buffer.Length, socketFlags, ref remoteEP);
}
- public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
+ public int ReceiveFrom (byte [] buffer, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, size);
- return ReceiveFrom (buffer, 0, size, flags, ref remoteEP);
+ return ReceiveFrom (buffer, 0, size, socketFlags, ref remoteEP);
}
- public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
+ public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
throw new ArgumentNullException ("remoteEP");
int error;
- return ReceiveFrom_nochecks_exc (buffer, offset, size, flags, ref remoteEP, true, out error);
+ return ReceiveFrom_nochecks_exc (buffer, offset, size, socketFlags, ref remoteEP, true, out error);
}
public bool ReceiveFromAsync (SocketAsyncEventArgs e)
return ret;
}
- public int Send (byte [] buffer, SocketFlags flags)
+ public int Send (byte [] buffer, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
SocketError error;
- int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
+ int ret = Send_nochecks (buffer, 0, buffer.Length, socketFlags, out error);
if (error != SocketError.Success)
throw new SocketException ((int) error);
return ret;
}
- public int Send (byte [] buffer, int size, SocketFlags flags)
+ public int Send (byte [] buffer, int size, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, size);
SocketError error;
- int ret = Send_nochecks (buffer, 0, size, flags, out error);
+ int ret = Send_nochecks (buffer, 0, size, socketFlags, out error);
if (error != SocketError.Success)
throw new SocketException ((int) error);
return ret;
}
- public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
+ public int Send (byte [] buffer, int offset, int size, SocketFlags socketFlags)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, offset, size);
SocketError error;
- int ret = Send_nochecks (buffer, offset, size, flags, out error);
+ int ret = Send_nochecks (buffer, offset, size, socketFlags, out error);
if (error != SocketError.Success)
throw new SocketException ((int) error);
return ret;
}
- public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
+ public int Send (byte [] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, offset, size);
- return Send_nochecks (buffer, offset, size, flags, out error);
+ return Send_nochecks (buffer, offset, size, socketFlags, out errorCode);
}
public
#region SendTo
- public int SendTo (byte [] buffer, EndPoint remote_end)
+ public int SendTo (byte [] buffer, EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
+ return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remoteEP);
}
- public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
+ public int SendTo (byte [] buffer, SocketFlags socketFlags, EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- return SendTo (buffer, 0, buffer.Length, flags, remote_end);
+ return SendTo (buffer, 0, buffer.Length, socketFlags, remoteEP);
}
- public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
+ public int SendTo (byte [] buffer, int size, SocketFlags socketFlags, EndPoint remoteEP)
{
- return SendTo (buffer, 0, size, flags, remote_end);
+ return SendTo (buffer, 0, size, socketFlags, remoteEP);
}
- public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
+ public int SendTo (byte [] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, offset, size);
- if (remote_end == null)
- throw new ArgumentNullException("remote_end");
+ if (remoteEP == null)
+ throw new ArgumentNullException("remoteEP");
- return SendTo_nochecks (buffer, offset, size, flags, remote_end);
+ return SendTo_nochecks (buffer, offset, size, socketFlags, remoteEP);
}
public bool SendToAsync (SocketAsyncEventArgs e)
throw new SocketException (error);
}
- public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
+ public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionLength)
{
ThrowIfDisposedAndClosed ();
int error;
- byte[] byte_val = new byte [length];
+ byte[] byte_val = new byte [optionLength];
GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
if (error != 0)
#region IOControl
- public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
+ public int IOControl (int ioControlCode, byte [] optionInValue, byte [] optionOutValue)
{
if (is_disposed)
throw new ObjectDisposedException (GetType ().ToString ());
int error;
- int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
+ int result = IOControl_internal (safe_handle, ioControlCode, optionInValue, optionOutValue, out error);
if (error != 0)
throw new SocketException (error);
newWebHeaders.Add(headerName,webHeaders[headerName]);
}
- webHeaders = newWebHeaders;
+ this.webHeaders = newWebHeaders;
}
}
public sealed class SemaphoreAccessRule : AccessRule
{
public SemaphoreAccessRule (IdentityReference identity,
- SemaphoreRights semaphoreRights,
+ SemaphoreRights eventRights,
AccessControlType type)
- : base (identity, (int)semaphoreRights, false, InheritanceFlags.None, PropagationFlags.None, type)
+ : base (identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type)
{
}
public SemaphoreAccessRule (string identity,
- SemaphoreRights semaphoreRights,
+ SemaphoreRights eventRights,
AccessControlType type)
- : this (new NTAccount (identity), semaphoreRights, type)
+ : this (new NTAccount (identity), eventRights, type)
{
}
: AuditRule
{
public SemaphoreAuditRule (IdentityReference identity,
- SemaphoreRights semaphoreRights,
+ SemaphoreRights eventRights,
AuditFlags flags)
- : base (identity, (int)semaphoreRights, false, InheritanceFlags.None, PropagationFlags.None, flags)
+ : base (identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
// methods
- public override void CopyFrom (AsnEncodedData encodedData)
+ public override void CopyFrom (AsnEncodedData asnEncodedData)
{
- if (encodedData == null)
- throw new ArgumentNullException ("encodedData");
+ if (asnEncodedData == null)
+ throw new ArgumentNullException ("asnEncodedData");
- X509Extension ex = (encodedData as X509Extension);
+ X509Extension ex = (asnEncodedData as X509Extension);
if (ex == null)
- throw new ArgumentException (Locale.GetText ("Wrong type."), "encodedData");
+ throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
if (ex._oid == null)
_oid = new Oid (oid, friendlyName);
// methods
- public override void CopyFrom (AsnEncodedData encodedData)
+ public override void CopyFrom (AsnEncodedData asnEncodedData)
{
- if (encodedData == null)
- throw new ArgumentNullException ("encodedData");
+ if (asnEncodedData == null)
+ throw new ArgumentNullException ("asnEncodedData");
- X509Extension ex = (encodedData as X509Extension);
+ X509Extension ex = (asnEncodedData as X509Extension);
if (ex == null)
- throw new ArgumentException (Locale.GetText ("Wrong type."), "encodedData");
+ throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
if (ex._oid == null)
_oid = new Oid (oid, friendlyName);
return new MemoryStream (Encoding.UTF8.GetBytes (s));
}
-#if NET_4_5
[Test]
public void CheckNet45Overloads () // Xambug #21982
{
decompressing.Close();
backing.Close();
}
-#endif
[Test]
[ExpectedException (typeof (ArgumentException))]
return new MemoryStream (Encoding.UTF8.GetBytes (s));
}
-#if NET_4_5
[Test]
public void CheckNet45Overloads () // Xambug #21982
{
decompressing.Close();
backing.Close();
}
-#endif
}
}
Socket sock = new Socket (AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
-
+
Assert.AreEqual (false, sock.NoDelay, "NoDelayDefaultTcp");
-
+
sock.Close ();
}
[Test]
public void ConnectToIPV4EndPointUsingDualModelSocket () {
- using (var server = new Socket (SocketType.Stream, ProtocolType.Tcp))
- using (var client = new Socket (SocketType.Stream, ProtocolType.Tcp)) {
+ /*
+ * IPv6 DualMode sockets are defaults in Mono. Explicitly specify that
+ * anyways in this test to make it more interoparable with .NET where
+ * IPv6 and DualMode needs to be specified.
+ */
+ using (var server = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp)) {
+
var host = new IPEndPoint (IPAddress.Loopback, NetworkHelpers.FindFreePort ());
-
+
+ server.DualMode = true;
server.Bind (host);
- server.Listen (0);
+ /*
+ * Nothing to Accept the connect - we need a backlog to make sure we don't get
+ Connection refused.
+ */
+ server.Listen (3);
var ep = server.LocalEndPoint as IPEndPoint;
-
+ var client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
client.Connect (ep);
- client.Disconnect (true);
-
+ client.Disconnect (false);
+ client.Close ();
+
+ client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
client.Connect (IPAddress.Loopback, ep.Port);
- client.Disconnect (true);
-
- client.Connect (new [] {IPAddress.Loopback}, ep.Port);
- client.Disconnect (true);
+ client.Disconnect (false);
+ client.Close ();
+
+ client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
+ client.Connect (new [] { IPAddress.Loopback }, ep.Port);
+ client.Disconnect (false);
+ client.Close ();
}
}
[Test]
public void BeginConnectToIPV4EndPointUsingDualModelSocket () {
- using (var server = new Socket (SocketType.Stream, ProtocolType.Tcp))
- using (var client = new Socket (SocketType.Stream, ProtocolType.Tcp)) {
+ /*
+ * IPv6 DualMode sockets are defaults in Mono. Explicitly specify that
+ * anyways in this test to make it more interoparable with .NET where
+ * IPv6 and DualMode needs to be specified.
+ */
+ using (var server = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
+ {
var host = new IPEndPoint (IPAddress.Loopback, NetworkHelpers.FindFreePort ());
-
+
+ server.DualMode = true;
server.Bind (host);
- server.Listen (0);
+ server.Listen (10);
var ep = server.LocalEndPoint as IPEndPoint;
-
+
BCCalledBack.Reset ();
+ var client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
var ar1 = client.BeginConnect (ep, BCCallback, client);
Assert.IsTrue (BCCalledBack.WaitOne (10000), "#1");
- client.Disconnect (true);
-
+ client.Disconnect (false);
+ client.Close ();
+
BCCalledBack.Reset ();
+ client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
var ar2 = client.BeginConnect (IPAddress.Loopback, ep.Port, BCCallback, client);
Assert.IsTrue (BCCalledBack.WaitOne (10000), "#2");
- client.Disconnect (true);
-
+ client.Disconnect (false);
+ client.Close ();
+
BCCalledBack.Reset ();
+ client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ client.DualMode = true;
var ar3 = client.BeginConnect (new [] {IPAddress.Loopback}, ep.Port, BCCallback, client);
Assert.IsTrue (BCCalledBack.WaitOne (10000), "#2");
- client.Disconnect (true);
+ client.Disconnect (false);
+ client.Close();
}
}
-#if NET_4_5
using System;
using System.Net;
using System.Threading;
}
}
-#endif
}
}
-#if NET_4_5
[Test]
public void AllowReadStreamBuffering ()
{
} catch (InvalidOperationException) {
}
}
-#endif
class ListenerScope : IDisposable {
EventWaitHandle completed;
Assert.AreSame (wc.Proxy, WebRequest.DefaultWebProxy);
}
-#if NET_4_5
[Test]
[Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
public void UploadStringAsyncCancelEvent ()
}
listener.Close ();
}
-#endif
public void UploadAsyncCancelEventTest (int port, Action<WebClient, Uri, EventWaitHandle> uploadAction)
{
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.IO;
using System.Collections.Generic;
}
}
}
-#endif
public void Setup()
{
StringTester.CreateMode = createMode;
-#if NET_4_5
StringTester.Location = location + "NET_4_5";
-#else
- StringTester.Location = location + "NET_4_0";
-#endif
}
[TearDown]
{
Uri u = new Uri("http://localhost/index.asp#main#start", false);
-#if NET_4_5
Assert.AreEqual (u.Fragment, "#main#start", "#1");
-#else
- Assert.AreEqual (u.Fragment, "#main%23start", "#1");
-#endif
u = new Uri("http://localhost/index.asp#main#start", true);
Assert.AreEqual (u.Fragment, "#main#start", "#2");
Uri b = new Uri ("http://www.gnome.org");
Uri n = new Uri (b, "blah#main#start");
-#if NET_4_5
Assert.AreEqual (n.Fragment, "#main#start", "#3");
-#else
- Assert.AreEqual (n.Fragment, "#main%23start", "#3");
-#endif
n = new Uri (b, "blah#main#start", true);
Assert.AreEqual (n.Fragment, "#main#start", "#4");
Uri ftp = new Uri ("FTP://[::ffFF:169.32.14.5]/");
Assert.AreEqual ("ftp", ftp.Scheme, "#7");
-#if NET_4_5
Assert.AreEqual ("[::ffff:169.32.14.5]", ftp.Host, "#8");
Assert.AreEqual ("ftp://[::ffff:169.32.14.5]/", ftp.ToString (), "#9");
-#else
- Assert.AreEqual ("[0000:0000:0000:0000:0000:FFFF:A920:0E05]", ftp.Host, "#8");
- Assert.AreEqual ("ftp://[0000:0000:0000:0000:0000:FFFF:A920:0E05]/", ftp.ToString (), "#9");
-#endif
}
[Test]
for (int i = 0; i < 128; i++)
sb.Append ((char) i);
-#if NET_4_5
Assert.AreEqual (
"%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F",
Uri.EscapeDataString (sb.ToString ()));
-#else
- Assert.AreEqual (
- "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22%23%24%25%26'()*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F",
- Uri.EscapeDataString (sb.ToString ()));
-#endif
Assert.AreEqual ("%C3%A1", Uri.EscapeDataString ("á"));
}
for (int i = 0; i < 128; i++)
sb.Append ((char) i);
-#if NET_4_5
Assert.AreEqual (
"%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[%5C]%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F",
Uri.EscapeUriString (sb.ToString ()));
-#else
- Assert.AreEqual (
- "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F",
- Uri.EscapeUriString (sb.ToString ()));
-#endif
Assert.AreEqual ("%C3%A1", Uri.EscapeDataString ("á"));
}
public void SetValue (RegistryKey rkey, string name, object value, RegistryValueKind valueKind)
{
Type type = value.GetType ();
- int result;
IntPtr handle = GetHandle (rkey);
- if (valueKind == RegistryValueKind.QWord && type == typeof (long)) {
- long rawValue = (long)value;
- result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.QWord, ref rawValue, Int64ByteSize);
- } else if (valueKind == RegistryValueKind.DWord && type == typeof (int)) {
- int rawValue = (int)value;
- result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize);
- } else if (valueKind == RegistryValueKind.Binary && type == typeof (byte[])) {
- byte[] rawValue = (byte[]) value;
- result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length);
- } else if (valueKind == RegistryValueKind.MultiString && type == typeof (string[])) {
- string[] vals = (string[]) value;
- StringBuilder fullStringValue = new StringBuilder ();
- foreach (string v in vals)
- {
- fullStringValue.Append (v);
- fullStringValue.Append ('\0');
+ switch (valueKind) {
+ case RegistryValueKind.QWord:
+ try {
+ long rawValue = Convert.ToInt64 (value);
+ CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.QWord, ref rawValue, Int64ByteSize));
+ return;
+ } catch (OverflowException) {
}
- fullStringValue.Append ('\0');
+ break;
+ case RegistryValueKind.DWord:
+ try {
+ int rawValue = Convert.ToInt32 (value);
+ CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize));
+ return;
+ } catch (OverflowException) {
+ }
+ break;
+ case RegistryValueKind.Binary:
+ if (type == typeof (byte[])) {
+ byte[] rawValue = (byte[]) value;
+ CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length));
+ return;
+ }
+ break;
+ case RegistryValueKind.MultiString:
+ if (type == typeof (string[])) {
+ string[] vals = (string[]) value;
+ StringBuilder fullStringValue = new StringBuilder ();
+ foreach (string v in vals)
+ {
+ fullStringValue.Append (v);
+ fullStringValue.Append ('\0');
+ }
+ fullStringValue.Append ('\0');
- byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ());
+ byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ());
- result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length);
- } else if ((valueKind == RegistryValueKind.String || valueKind == RegistryValueKind.ExpandString) &&
- type == typeof (string)){
- string rawValue = String.Format ("{0}{1}", value, '\0');
- result = RegSetValueEx (handle, name, IntPtr.Zero, valueKind, rawValue,
- rawValue.Length * NativeBytesPerCharacter);
-
- } else if (type.IsArray) {
- throw new ArgumentException ("Only string and byte arrays can written as registry values");
- } else {
- throw new ArgumentException ("Type does not match the valueKind");
+ CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length));
+ return;
+ }
+ break;
+ case RegistryValueKind.String:
+ case RegistryValueKind.ExpandString:
+ if (type == typeof (string)) {
+ string rawValue = String.Format ("{0}{1}", value, '\0');
+ CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, valueKind, rawValue,
+ rawValue.Length * NativeBytesPerCharacter));
+ return;
+ }
+ break;
+ default:
+ if (type.IsArray) {
+ throw new ArgumentException ("Only string and byte arrays can written as registry values");
+ }
+ break;
}
- // handle the result codes
- if (result != Win32ResultCode.Success)
- {
- GenerateException (result);
- }
+ throw new ArgumentException ("Type does not match the valueKind");
}
public void SetValue (RegistryKey rkey, string name, object value)
rawValue.Length * NativeBytesPerCharacter);
}
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
// handle the result codes
if (result != Win32ResultCode.Success)
{
int result = RegEnumKey (handle, index, stringBuffer,
stringBuffer.Capacity);
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
if (result == Win32ResultCode.Success)
continue;
IntPtr.Zero, ref type,
IntPtr.Zero, IntPtr.Zero);
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
continue;
RegOptionsNonVolatile,
OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition);
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
if (result != Win32ResultCode.Success) {
GenerateException (result);
}
options == RegistryOptions.Volatile ? RegOptionsVolatile : RegOptionsNonVolatile,
OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition);
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
if (result != Win32ResultCode.Success)
GenerateException (result);
if (result == Win32ResultCode.NoMoreEntries)
break;
- if (result == Win32ResultCode.MarkedForDeletion)
- throw RegistryKey.CreateMarkedForDeletionException ();
-
GenerateException (result);
}
return values.ToArray ();
}
+ private void CheckResult (int result)
+ {
+ if (result != Win32ResultCode.Success) {
+ GenerateException (result);
+ }
+ }
+
/// <summary>
/// convert a win32 error code into an appropriate exception.
/// </summary>
throw new IOException ("The network path was not found.");
case Win32ResultCode.InvalidHandle:
throw new IOException ("Invalid handle.");
+ case Win32ResultCode.MarkedForDeletion:
+ throw RegistryKey.CreateMarkedForDeletionException ();
+ case Win32ResultCode.ChildMustBeVolatile:
+ throw new IOException ("Cannot create a stable subkey under a volatile parent key.");
default:
// unidentified system exception
throw new SystemException ();
public const int NetworkPathNotFound = 53;
public const int NoMoreEntries = 259;
public const int MarkedForDeletion = 1018;
+ public const int ChildMustBeVolatile = 1021;
}
}
}
// 5 path
- pos = uriString.IndexOfAny (new char[] {'/'});
+ pos = uriString.IndexOfAny (new char[] {'/', '\\'});
if (unixAbsPath)
pos = -1;
if (pos == -1) {
pos = uriString.LastIndexOf (":");
if (unixAbsPath)
pos = -1;
+ if (pos == 1 && scheme == Uri.UriSchemeFile && Char.IsLetter (uriString [0]))
+ pos = -1;
if (pos != -1 && pos != (uriString.Length - 1)) {
string portStr = uriString.Remove (0, pos + 1);
if (portStr.Length > 1 && portStr [portStr.Length - 1] != ']') {
using System;
using System.Runtime.InteropServices;
+#pragma warning disable 169
+
namespace Mono {
//
// Managed representations of mono runtime types
static class AppContextSwitches {
public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true;
public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false;
+ public static readonly bool NoAsyncCurrentCulture = false;
}
}
\ No newline at end of file
return i != 0;
}
- public static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+ internal void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
{
var declaringType = mi.DeclaringType;
if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
const int CalendarTypeBits = 8;
const string MSG_READONLY = "This instance is read only";
+
+ static volatile CultureInfo s_DefaultThreadCurrentUICulture;
+ static volatile CultureInfo s_DefaultThreadCurrentCulture;
public static CultureInfo InvariantCulture {
get {
get {
return Thread.CurrentThread.CurrentCulture;
}
-#if NETSTANDARD
set {
- throw new NotImplementedException ();
+ Thread.CurrentThread.CurrentCulture = value;
}
-#endif
}
public static CultureInfo CurrentUICulture {
get {
return Thread.CurrentThread.CurrentUICulture;
}
-#if NETSTANDARD
set {
- throw new NotImplementedException ();
+ Thread.CurrentThread.CurrentUICulture = value;
}
-#endif
}
internal static CultureInfo ConstructCurrentCulture ()
}
}
- internal void CheckNeutral ()
+ void CheckNeutral ()
{
}
public static CultureInfo DefaultThreadCurrentCulture {
get {
- return Thread.default_culture;
+ return s_DefaultThreadCurrentCulture;
}
set {
- Thread.default_culture = value;
+ s_DefaultThreadCurrentCulture = value;
}
}
public static CultureInfo DefaultThreadCurrentUICulture {
get {
- return Thread.default_ui_culture;
+ return s_DefaultThreadCurrentUICulture;
}
set {
- Thread.default_ui_culture = value;
+ s_DefaultThreadCurrentUICulture = value;
}
}
}
}
+ internal static CultureInfo UserDefaultUICulture {
+ get {
+ return ConstructCurrentUICulture ();
+ }
+ }
+
+ internal static CultureInfo UserDefaultCulture {
+ get {
+ return ConstructCurrentCulture ();
+ }
+ }
+
+
#region reference sources
// TODO:
internal static readonly bool IsTaiwanSku;
return true;
}
+ internal static bool VerifyCultureName(CultureInfo culture, bool throwException) {
+ Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null");
+
+ //If we have an instance of one of our CultureInfos, the user can't have changed the
+ //name and we know that all names are valid in files.
+ if (!culture.m_isInherited) {
+ return true;
+ }
+
+ return VerifyCultureName(culture.Name, throwException);
+
+ }
+
#endregion
}
}
static internal IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption)
{
string path_with_pattern = Path.Combine (full, searchPattern);
- IntPtr handle;
+ IntPtr handle = IntPtr.Zero;
MonoIOError error;
FileAttributes rattr;
bool subdirs = searchOption == SearchOption.AllDirectories;
Path.Validate (full);
- string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle);
- if (s == null)
- yield break;
- if (error != 0)
- throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error);
-
try {
+ string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle);
+ if (s == null)
+ yield break;
+ if (error != 0)
+ throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error);
+
do {
if (((rattr & FileAttributes.ReparsePoint) == 0)){
if ((rattr & FileAttributes.Directory) != 0)
} while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null);
} finally {
- MonoIO.FindClose (handle);
+ if (handle != IntPtr.Zero)
+ MonoIO.FindClose (handle);
}
}
case MonoIOError.ERROR_NOT_SAME_DEVICE:
message = "Source and destination are not on the same device";
return new IOException (message, unchecked((int)0x80070000) | (int)error);
+
+ case MonoIOError.ERROR_DIRECTORY:
+ message = "The directory name is invalid";
+ return new IOException (message, unchecked((int)0x80070000) | (int)error);
default:
message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path);
WAIT_TIMEOUT = 258,\r
ERROR_NO_MORE_ITEMS = 259,\r
ERROR_CANNOT_COPY = 266,\r
- ERROR_DIRECTORY = 267,\r
- ERROR_EAS_DIDNT_FIT = 275,\r
+ */ ERROR_DIRECTORY = 267,\r
+ /* ERROR_EAS_DIDNT_FIT = 275,\r
ERROR_EA_FILE_CORRUPT = 276,\r
ERROR_EA_TABLE_FULL = 277,\r
ERROR_INVALID_EA_HANDLE = 278,\r
{
int l = s.Length;
int sub = 0;
+ int alt = 0;
int start = 0;
// Host prefix?
if (c != DirectorySeparatorChar && c != AltDirectorySeparatorChar)
continue;
+ if (DirectorySeparatorChar != AltDirectorySeparatorChar && c == AltDirectorySeparatorChar)
+ alt++;
if (i+1 == l)
sub++;
else {
}
}
- if (sub == 0)
+ if (sub == 0 && alt == 0)
return s;
char [] copy = new char [l-sub];
return DirectorySeparatorStr;
}
}
+
+ internal const int MAX_PATH = 260; // From WinDef.h
}
}
if (ilgen != null)
ilgen.label_fixup (this);
}
+
+ internal void ResolveUserTypes () {
+ TypeBuilder.ResolveUserTypes (parameters);
+ if (paramModReq != null) {
+ foreach (var types in paramModReq)
+ TypeBuilder.ResolveUserTypes (types);
+ }
+ if (paramModOpt != null) {
+ foreach (var types in paramModOpt)
+ TypeBuilder.ResolveUserTypes (types);
+ }
+ }
internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
{
throw new InvalidOperationException ("Unable to change after type has been created.");
}
+ internal void ResolveUserTypes () {
+ type = TypeBuilder.ResolveUserType (type);
+ TypeBuilder.ResolveUserTypes (modReq);
+ TypeBuilder.ResolveUserTypes (modOpt);
+ if (marshal_info != null)
+ marshal_info.marshaltyperef = TypeBuilder.ResolveUserType (marshal_info.marshaltyperef);
+ }
+
public override Module Module {
get {
return base.Module;
if (ilgen != null)
ilgen.label_fixup (this);
}
-
+
+ internal void ResolveUserTypes () {
+ rtype = TypeBuilder.ResolveUserType (rtype);
+ TypeBuilder.ResolveUserTypes (parameters);
+ TypeBuilder.ResolveUserTypes (returnModReq);
+ TypeBuilder.ResolveUserTypes (returnModOpt);
+ if (paramModReq != null) {
+ foreach (var types in paramModReq)
+ TypeBuilder.ResolveUserTypes (types);
+ }
+ if (paramModOpt != null) {
+ foreach (var types in paramModOpt)
+ TypeBuilder.ResolveUserTypes (types);
+ }
+ }
+
internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
{
if (ilgen != null && ilgen.HasDebugInfo) {
public byte[] GetSignature ()
{
+ TypeBuilder.ResolveUserTypes (arguments);
+
switch (type) {
case SignatureHelperType.HELPER_LOCAL:
return get_signature_local ();
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void setup_internal_class (TypeBuilder tb);
+ private extern void setup_internal_class ();
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void create_internal_class (TypeBuilder tb);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void setup_generic_class ();
-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void create_generic_class ();
this.nspace = String.Empty;
this.fullname = TypeIdentifiers.WithoutEscape(this.tname);
pmodule = mb;
- setup_internal_class (this);
+ setup_internal_class ();
}
internal TypeBuilder (ModuleBuilder mb, string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packing_size, int type_size, Type nesting_type)
{
int sep_index;
- this.parent = parent;
+ this.parent = ResolveUserType (parent);
this.attrs = attr;
this.class_size = type_size;
this.packing_size = packing_size;
// skip .<Module> ?
table_idx = mb.get_next_table_index (this, 0x02, true);
- setup_internal_class (this);
+ setup_internal_class ();
fullname = GetFullName ();
}
fields = new FieldBuilder [1];
fields [0] = res;
num_fields ++;
- create_internal_class (this);
}
if (IsEnum) {
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern TypeInfo create_runtime_class (TypeBuilder tb);
+ private extern TypeInfo create_runtime_class ();
private bool is_nested_in (Type t)
{
ctor.fixup ();
}
- created = create_runtime_class (this);
+ ResolveUserTypes ();
+
+ created = create_runtime_class ();
if (created != null)
return created;
return this;
}
+ void ResolveUserTypes () {
+ parent = ResolveUserType (parent);
+ ResolveUserTypes (interfaces);
+ if (fields != null) {
+ foreach (var fb in fields) {
+ if (fb != null)
+ fb.ResolveUserTypes ();
+ }
+ }
+ if (methods != null) {
+ foreach (var mb in methods) {
+ if (mb != null)
+ mb.ResolveUserTypes ();
+ }
+ }
+ if (ctors != null) {
+ foreach (var cb in ctors) {
+ if (cb != null)
+ cb.ResolveUserTypes ();
+ }
+ }
+ }
+
+ static internal void ResolveUserTypes (Type[] types) {
+ if (types != null)
+ for (int i = 0; i < types.Length; ++i)
+ types [i] = ResolveUserType (types [i]);
+ }
+
+ static internal Type ResolveUserType (Type t) {
+ if (t != null && ((t.GetType ().Assembly != typeof (int).Assembly) || (t is TypeDelegator))) {
+ t = t.UnderlyingSystemType;
+ if (t != null && ((t.GetType ().Assembly != typeof (int).Assembly) || (t is TypeDelegator)))
+ throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
+ return t;
+ } else {
+ return t;
+ }
+ }
+
internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
{
symbolWriter.OpenNamespace (this.Namespace);
} else {
this.parent = parent;
}
+ this.parent = ResolveUserType (this.parent);
// will just set the parent-related bits if called a second time
- setup_internal_class (this);
+ setup_internal_class ();
}
internal int get_next_table_index (object obj, int table, bool inc) {
if (names.Length == 0)
throw new ArgumentException ("names");
- setup_generic_class ();
-
generic_params = new GenericTypeParameterBuilder [names.Length];
for (int i = 0; i < names.Length; i++) {
string item = names [i];
string guid;
string mcookie;
string marshaltype;
- Type marshaltyperef;
+ internal Type marshaltyperef;
private int param_num;
private bool has_size;
#pragma warning restore 169, 414
get {
return (cultureinfo == null)? null : cultureinfo.Name;
}
-#if NETSTANDARD
set {
throw new NotImplementedException ();
}
-#endif
}
[ComVisibleAttribute(false)]
using System.Security;
using System.Reflection;
using System.Threading;
+using System.Runtime.InteropServices.ComTypes;
using System.Runtime.ConstrainedExecution;
#if !FULL_AOT_RUNTIME
-using System.Runtime.InteropServices.ComTypes;
using Mono.Interop;
#endif
return CreateAggregatedObject (pOuter, (object)o);
}
-#if !FULL_AOT_RUNTIME
public static object CreateWrapperOfType (object o, Type t)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
__ComObject co = o as __ComObject;
if (co == null)
throw new ArgumentException ("o must derive from __ComObject", "o");
}
return ComInteropProxy.GetProxy (co.IUnknown, t).GetTransparentProxy ();
+#endif
}
public static TWrapper CreateWrapperOfType<T, TWrapper> (T o) {
return (TWrapper)CreateWrapperOfType ((object)o, typeof (TWrapper));
}
-#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ComVisible (true)]
return GetCCW (o, T);
}
#endif
+#endif // !FULL_AOT_RUNTIME
public static IntPtr GetComInterfaceForObject (object o, Type T)
{
-#if !MOBILE
+#if MOBILE
+ throw new PlatformNotSupportedException ();
+#else
IntPtr pItf = GetComInterfaceForObjectInternal (o, T);
AddRef (pItf);
return pItf;
-#else
- throw new NotImplementedException ();
#endif
}
return GetComInterfaceForObject ((object)o, typeof (T));
}
+#if !FULL_AOT_RUNTIME
[MonoTODO]
public static IntPtr GetComInterfaceForObjectInContext (object o, Type t)
{
throw new NotImplementedException ();
}
- [MonoTODO]
- public static int GetExceptionCode()
- {
- throw new NotImplementedException ();
- }
-
[MonoTODO]
[ComVisible (true)]
public static IntPtr GetExceptionPointers()
}
#endif // !FULL_AOT_RUNTIME
-#if !FULL_AOT_RUNTIME
+ public static int GetExceptionCode ()
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
public static int GetHRForException (Exception e)
{
+ if (e == null) return 0;
+
#if FEATURE_COMINTEROP
var errorInfo = new ManagedErrorInfo(e);
SetErrorInfo (0, errorInfo);
+#endif
return e._HResult;
-#else
- return -1;
-#endif
}
[MonoTODO]
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public static int GetHRForLastWin32Error()
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
throw new NotImplementedException ();
+#endif
}
+#if !FULL_AOT_RUNTIME
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static IntPtr GetIDispatchForObjectInternal (object o);
throw new NotImplementedException ();
}
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static IntPtr GetIUnknownForObjectInternal (object o);
-
- public static IntPtr GetIUnknownForObject (object o)
- {
- IntPtr pUnk = GetIUnknownForObjectInternal (o);
- // Internal method does not AddRef
- AddRef (pUnk);
- return pUnk;
- }
-
[MonoTODO]
public static IntPtr GetIUnknownForObjectInContext (object o)
{
throw new NotImplementedException ();
}
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static IntPtr GetIUnknownForObjectInternal (object o);
+
+#endif // !FULL_AOT_RUNTIME
+
+ public static IntPtr GetIUnknownForObject (object o)
+ {
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
+ IntPtr pUnk = GetIUnknownForObjectInternal (o);
+ // Internal method does not AddRef
+ AddRef (pUnk);
+ return pUnk;
+#endif
+ }
+
public static void GetNativeVariantForObject (object obj, IntPtr pDstNativeVariant)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
Variant vt = new Variant();
vt.SetValue(obj);
Marshal.StructureToPtr(vt, pDstNativeVariant, false);
+#endif
}
public static void GetNativeVariantForObject<T> (T obj, IntPtr pDstNativeVariant) {
GetNativeVariantForObject ((object)obj, pDstNativeVariant);
}
-#if !MOBILE
+#if !MOBILE && !FULL_AOT_RUNTIME
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private static extern object GetObjectForCCW (IntPtr pUnk);
#endif
public static object GetObjectForIUnknown (IntPtr pUnk)
{
-#if !MOBILE
+#if MOBILE || FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
object obj = GetObjectForCCW (pUnk);
// was not a CCW
if (obj == null) {
obj = proxy.GetTransparentProxy ();
}
return obj;
-#else
- throw new NotImplementedException ();
#endif
}
public static object GetObjectForNativeVariant (IntPtr pSrcNativeVariant)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
Variant vt = (Variant)Marshal.PtrToStructure(pSrcNativeVariant, typeof(Variant));
return vt.GetValue();
+#endif
}
- public static T GetObjectForNativeVariant<T> (IntPtr pSrcNativeVariant) {
+ public static T GetObjectForNativeVariant<T> (IntPtr pSrcNativeVariant)
+ {
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
Variant vt = (Variant)Marshal.PtrToStructure(pSrcNativeVariant, typeof(Variant));
return (T)vt.GetValue();
+#endif
}
public static object[] GetObjectsForNativeVariants (IntPtr aSrcNativeVariant, int cVars)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
if (cVars < 0)
throw new ArgumentOutOfRangeException ("cVars", "cVars cannot be a negative number.");
object[] objects = new object[cVars];
objects[i] = GetObjectForNativeVariant ((IntPtr)(aSrcNativeVariant.ToInt64 () +
i * SizeOf (typeof(Variant))));
return objects;
+#endif
}
- public static T[] GetObjectsForNativeVariants<T> (IntPtr aSrcNativeVariant, int cVars) {
+ public static T[] GetObjectsForNativeVariants<T> (IntPtr aSrcNativeVariant, int cVars)
+ {
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
if (cVars < 0)
throw new ArgumentOutOfRangeException ("cVars", "cVars cannot be a negative number.");
T[] objects = new T[cVars];
objects[i] = GetObjectForNativeVariant<T> ((IntPtr)(aSrcNativeVariant.ToInt64 () +
i * SizeOf (typeof(Variant))));
return objects;
+#endif
}
[MonoTODO]
public static int GetStartComSlot (Type t)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
throw new NotImplementedException ();
+#endif
}
+#if !FULL_AOT_RUNTIME
[MonoTODO]
[Obsolete ("This method has been deprecated")]
public static Thread GetThreadFromFiberCookie (int cookie)
throw new NotImplementedException ();
}
- public static Type GetTypeFromCLSID (Guid clsid)
- {
- throw new NotImplementedException ();
- }
-
-#if !FULL_AOT_RUNTIME
[Obsolete]
[MonoTODO]
public static string GetTypeInfoName (UCOMITypeInfo pTI)
throw new NotImplementedException ();
}
- public static string GetTypeInfoName (ITypeInfo typeInfo)
- {
- throw new NotImplementedException ();
- }
-
[Obsolete]
[MonoTODO]
public static Guid GetTypeLibGuid (UCOMITypeLib pTLB)
throw new NotImplementedException ();
}
- public static object GetUniqueObjectForIUnknown (IntPtr unknown)
- {
- throw new NotImplementedException ();
- }
-#endif
-
[MonoTODO]
[Obsolete ("This method has been deprecated")]
public static IntPtr GetUnmanagedThunkForManagedMethodPtr (IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature)
throw new NotImplementedException ();
}
-#if !MOBILE
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern static bool IsComObject (object o);
-#else
- public static bool IsComObject (object o)
- {
- throw new NotImplementedException ();
- }
-#endif
-
[MonoTODO]
public static bool IsTypeVisibleFromCom (Type t)
{
{
throw new NotImplementedException ();
}
+#endif // !FULL_AOT_RUNTIME
+
+ public static Type GetTypeFromCLSID (Guid clsid)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ public static string GetTypeInfoName (ITypeInfo typeInfo)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ public static object GetUniqueObjectForIUnknown (IntPtr unknown)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+#if !MOBILE
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ public extern static bool IsComObject (object o);
+#else
+ public static bool IsComObject (object o)
+ {
+ throw new PlatformNotSupportedException ();
+ }
#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
#if !FULL_AOT_RUNTIME
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static int ReleaseComObjectInternal (object co);
+#endif
public static int ReleaseComObject (object o)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
if (o == null)
throw new ArgumentException ("Value cannot be null.", "o");
if (!IsComObject (o))
throw new ArgumentException ("Value must be a Com object.", "o");
return ReleaseComObjectInternal (o);
+#endif
}
+#if !FULL_AOT_RUNTIME
[Obsolete]
[MonoTODO]
public static void ReleaseThreadCache()
#endif
}
-#if !FULL_AOT_RUNTIME
public static int FinalReleaseComObject (object o)
{
while (ReleaseComObject (o) != 0);
return 0;
}
-#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern Delegate GetDelegateForFunctionPointerInternal (IntPtr ptr, Type t);
old_state = _state;
if ((old_state & (int) State.Closed) != 0)
- throw new ObjectDisposedException ("handle");
+ throw new ObjectDisposedException (null, "Safe handle has been closed");
new_state = old_state + RefCount_One;
} while (Interlocked.CompareExchange (ref _state, new_state, old_state) != old_state);
* hitting zero though -- that can happen if SetHandleAsInvalid is
* used). */
if ((old_state & RefCount_Mask) == 0)
- throw new ObjectDisposedException ("handle");
+ throw new ObjectDisposedException (null, "Safe handle has been closed");
if ((old_state & RefCount_Mask) != RefCount_One)
perform_release = false;
{
Persist (name, includeSections, null);
}
+
+ internal void Persist (SafeHandle handle)
+ {
+ PersistModifications (handle);
+ }
internal void PersistModifications (SafeHandle handle)
{
--- /dev/null
+//
+// CryptoConfig.cs: Handles cryptographic implementations and OIDs mappings.
+//
+// Author:
+// Sebastien Pouliot (sebastien@ximian.com)
+// Tim Coleman (tim@timcoleman.com)
+//
+// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) Tim Coleman, 2004
+// Copyright (C) 2004-2007, 2009 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Security.Cryptography {
+
+ public partial class CryptoConfig {
+
+ public static byte[] EncodeOID (string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException ("str");
+ char[] delim = { '.' };
+ string[] parts = str.Split (delim);
+ // according to X.208 n is always at least 2
+ if (parts.Length < 2) {
+ throw new CryptographicUnexpectedOperationException (
+ Locale.GetText ("OID must have at least two parts"));
+ }
+
+ // we're sure that the encoded OID is shorter than its string representation
+ byte[] oid = new byte [str.Length];
+ // now encoding value
+ try {
+ byte part0 = Convert.ToByte (parts [0]);
+ // OID[0] > 2 is invalid but "supported" in MS BCL
+ // uncomment next line to trap this error
+ // if (part0 > 2) throw new CryptographicUnexpectedOperationException ();
+ byte part1 = Convert.ToByte (parts [1]);
+ // OID[1] >= 40 is illegal for OID[0] < 2 because of the % 40
+ // however the syntax is "supported" in MS BCL
+ // uncomment next 2 lines to trap this error
+ //if ((part0 < 2) && (part1 >= 40))
+ // throw new CryptographicUnexpectedOperationException ();
+ oid[2] = Convert.ToByte (part0 * 40 + part1);
+ }
+ catch {
+ throw new CryptographicUnexpectedOperationException (
+ Locale.GetText ("Invalid OID"));
+ }
+ int j = 3;
+ for (int i = 2; i < parts.Length; i++) {
+ long x = Convert.ToInt64 (parts [i]);
+ if (x > 0x7F) {
+ byte[] num = EncodeLongNumber (x);
+ Buffer.BlockCopy (num, 0, oid, j, num.Length);
+ j += num.Length;
+ }
+ else
+ oid[j++] = Convert.ToByte (x);
+ }
+
+ int k = 2;
+ // copy the exact number of byte required
+ byte[] oid2 = new byte [j];
+ oid2[0] = 0x06; // always - this tag means OID
+ // Length (of value)
+ if (j > 0x7F) {
+ // for compatibility with MS BCL
+ throw new CryptographicUnexpectedOperationException (
+ Locale.GetText ("OID > 127 bytes"));
+ // comment exception and uncomment next 3 lines to remove restriction
+ //byte[] num = EncodeLongNumber (j);
+ //Buffer.BlockCopy (num, 0, oid, j, num.Length);
+ //k = num.Length + 1;
+ }
+ else
+ oid2 [1] = Convert.ToByte (j - 2);
+
+ Buffer.BlockCopy (oid, k, oid2, k, j - k);
+ return oid2;
+ }
+
+ // encode (7bits array) number greater than 127
+ private static byte[] EncodeLongNumber (long x)
+ {
+ // for MS BCL compatibility
+ // comment next two lines to remove restriction
+ if ((x > Int32.MaxValue) || (x < Int32.MinValue))
+ throw new OverflowException (Locale.GetText ("Part of OID doesn't fit in Int32"));
+
+ long y = x;
+ // number of bytes required to encode this number
+ int n = 1;
+ while (y > 0x7F) {
+ y = y >> 7;
+ n++;
+ }
+ byte[] num = new byte [n];
+ // encode all bytes
+ for (int i = 0; i < n; i++) {
+ y = x >> (7 * i);
+ y = y & 0x7F;
+ if (i != 0)
+ y += 0x80;
+ num[n-i-1] = Convert.ToByte (y);
+ }
+ return num;
+ }
+
+ [MonoLimitation ("nothing is FIPS certified so it never make sense to restrict to this (empty) subset")]
+ public static bool AllowOnlyFipsAlgorithms {
+ get { return false; }
+ }
+ }
+}
+
static Type defaultMAC3DES = typeof (MACTripleDES);
// LAMESPEC: undocumented classes (also undocumented in CryptoConfig ;-)
static Type defaultDSASigDesc = typeof (DSASignatureDescription);
- static Type defaultRSASigDesc = typeof (RSAPKCS1SHA1SignatureDescription);
+ static Type defaultRSAPKCS1SHA1SigDesc = typeof (RSAPKCS1SHA1SignatureDescription);
+ static Type defaultRSAPKCS1SHA256SigDesc = typeof (RSAPKCS1SHA256SignatureDescription);
+ static Type defaultRSAPKCS1SHA384SigDesc = typeof (RSAPKCS1SHA384SignatureDescription);
+ static Type defaultRSAPKCS1SHA512SigDesc = typeof (RSAPKCS1SHA512SignatureDescription);
static Type defaultRIPEMD160 = typeof (RIPEMD160Managed);
static Type defaultHMACMD5 = typeof (HMACMD5);
static Type defaultHMACRIPEMD160 = typeof (HMACRIPEMD160);
// LAMESPEC: undocumented URLs in CryptoConfig
private const string urlDSASHA1 = urlXmlDsig + "dsa-sha1"; // no space
private const string urlRSASHA1 = urlXmlDsig + "rsa-sha1"; // no space
+ private const string urlRSASHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // no space
+ private const string urlRSASHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"; // no space
+ private const string urlRSASHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; // no space
private const string urlSHA1 = urlXmlDsig + "sha1"; // no space
private const string urlC14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
private const string urlC14NWithComments = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#";
private const string urlSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256";
+ private const string urlSHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384";
private const string urlSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512";
private const string urlHMACSHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
private const string urlHMACSHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
// add some of the XMLDSIG urls into machine.config (and they make a LOT
// of sense for implementing XMLDSIG in System.Security.Cryptography.Xml)
algorithms.Add (urlDSASHA1, defaultDSASigDesc);
- algorithms.Add (urlRSASHA1, defaultRSASigDesc);
+ algorithms.Add (urlRSASHA1, defaultRSAPKCS1SHA1SigDesc);
+ algorithms.Add (urlRSASHA256, defaultRSAPKCS1SHA256SigDesc);
+ algorithms.Add (urlRSASHA384, defaultRSAPKCS1SHA384SigDesc);
+ algorithms.Add (urlRSASHA512, defaultRSAPKCS1SHA512SigDesc);
algorithms.Add (urlSHA1, defaultSHA1);
unresolved_algorithms.Add (urlC14N, defaultC14N);
unresolved_algorithms.Add (urlC14NWithComments, defaultC14NWithComments);
unresolved_algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments);
unresolved_algorithms.Add (urlXmlDecryption, defaultXmlDecryption);
algorithms.Add (urlSHA256, defaultSHA256);
- // xmlenc does not include a definition for SHA384
+ algorithms.Add (urlSHA384, defaultSHA384);
algorithms.Add (urlSHA512, defaultSHA512);
algorithms.Add (urlHMACSHA256, defaultHMACSHA256);
algorithms.Add (urlHMACSHA384, defaultHMACSHA384);
oid.Add (nameSHA256, oidSHA256);
oid.Add (nameSHA256a, oidSHA256);
oid.Add (nameSHA256c, oidSHA256);
+ oid.Add (nameSHA256Cng, oidSHA256);
+ oid.Add (nameSHA256Provider, oidSHA256);
oid.Add (nameSHA384, oidSHA384);
oid.Add (nameSHA384a, oidSHA384);
oid.Add (nameSHA384c, oidSHA384);
+ oid.Add (nameSHA384Cng, oidSHA384);
+ oid.Add (nameSHA384Provider, oidSHA384);
oid.Add (nameSHA512, oidSHA512);
oid.Add (nameSHA512a, oidSHA512);
oid.Add (nameSHA512c, oidSHA512);
+ oid.Add (nameSHA512Cng, oidSHA512);
+ oid.Add (nameSHA512Provider, oidSHA512);
oid.Add (nameRIPEMD160, oidRIPEMD160);
oid.Add (nameRIPEMD160a, oidRIPEMD160);
case "system.security.cryptography.rsapkcs1sha1signaturedescription":
case "http://www.w3.org/2000/09/xmldsig#rsa-sha1":
return new RSAPKCS1SHA1SignatureDescription ();
+ case "system.security.cryptography.rsapkcs1sha256signaturedescription":
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256":
+ return new RSAPKCS1SHA256SignatureDescription ();
+ case "system.security.cryptography.rsapkcs1sha384signaturedescription":
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384":
+ return new RSAPKCS1SHA384SignatureDescription ();
+ case "system.security.cryptography.rsapkcs1sha512signaturedescription":
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512":
+ return new RSAPKCS1SHA512SignatureDescription ();
case "system.security.cryptography.hashalgorithm":
case "system.security.cryptography.sha1":
case "system.security.cryptography.sha1cryptoserviceprovider":
+ case "system.security.cryptography.sha1cng":
case "sha1":
case "sha":
case "http://www.w3.org/2000/09/xmldsig#sha1":
return new SHA1Managed ();
case "system.security.cryptography.sha256managed":
case "system.security.cryptography.sha256":
+ case "system.security.cryptography.sha256cryptoserviceprovider":
+ case "system.security.cryptography.sha256cng":
case "sha256":
case "sha-256":
case "http://www.w3.org/2001/04/xmlenc#sha256":
return new SHA256Managed ();
case "system.security.cryptography.sha384managed":
case "system.security.cryptography.sha384":
+ case "system.security.cryptography.sha384cryptoserviceprovider":
+ case "system.security.cryptography.sha384cng":
case "sha384":
case "sha-384":
+ case "http://www.w3.org/2001/04/xmldsig-more#sha384":
return new SHA384Managed ();
case "system.security.cryptography.sha512managed":
case "system.security.cryptography.sha512":
+ case "system.security.cryptography.sha512cryptoserviceprovider":
+ case "system.security.cryptography.sha512cng":
case "sha512":
case "sha-512":
case "http://www.w3.org/2001/04/xmlenc#sha512":
switch (name.ToLowerInvariant ()) {
case "system.security.cryptography.sha1cryptoserviceprovider":
+ case "system.security.cryptography.sha1cng":
case "system.security.cryptography.sha1managed":
case "system.security.cryptography.sha1":
case "sha1":
case "system.security.cryptography.md5":
case "md5":
return "1.2.840.113549.2.5";
+ case "system.security.cryptography.sha256cryptoserviceprovider":
+ case "system.security.cryptography.sha256cng":
case "system.security.cryptography.sha256managed":
case "system.security.cryptography.sha256":
case "sha256":
return "2.16.840.1.101.3.4.2.1";
+ case "system.security.cryptography.sha384cryptoserviceprovider":
+ case "system.security.cryptography.sha384cng":
case "system.security.cryptography.sha384managed":
case "system.security.cryptography.sha384":
case "sha384":
return "2.16.840.1.101.3.4.2.2";
+ case "system.security.cryptography.sha512cryptoserviceprovider":
+ case "system.security.cryptography.sha512cng":
case "system.security.cryptography.sha512managed":
case "system.security.cryptography.sha512":
case "sha512":
+++ /dev/null
-//
-// CryptoConfig.cs: Handles cryptographic implementations and OIDs mappings.
-//
-// Author:
-// Sebastien Pouliot (sebastien@ximian.com)
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2007, 2009 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace System.Security.Cryptography {
-
- public partial class CryptoConfig {
-
- public static byte[] EncodeOID (string str)
- {
- if (str == null)
- throw new ArgumentNullException ("str");
- char[] delim = { '.' };
- string[] parts = str.Split (delim);
- // according to X.208 n is always at least 2
- if (parts.Length < 2) {
- throw new CryptographicUnexpectedOperationException (
- Locale.GetText ("OID must have at least two parts"));
- }
-
- // we're sure that the encoded OID is shorter than its string representation
- byte[] oid = new byte [str.Length];
- // now encoding value
- try {
- byte part0 = Convert.ToByte (parts [0]);
- // OID[0] > 2 is invalid but "supported" in MS BCL
- // uncomment next line to trap this error
- // if (part0 > 2) throw new CryptographicUnexpectedOperationException ();
- byte part1 = Convert.ToByte (parts [1]);
- // OID[1] >= 40 is illegal for OID[0] < 2 because of the % 40
- // however the syntax is "supported" in MS BCL
- // uncomment next 2 lines to trap this error
- //if ((part0 < 2) && (part1 >= 40))
- // throw new CryptographicUnexpectedOperationException ();
- oid[2] = Convert.ToByte (part0 * 40 + part1);
- }
- catch {
- throw new CryptographicUnexpectedOperationException (
- Locale.GetText ("Invalid OID"));
- }
- int j = 3;
- for (int i = 2; i < parts.Length; i++) {
- long x = Convert.ToInt64 (parts [i]);
- if (x > 0x7F) {
- byte[] num = EncodeLongNumber (x);
- Buffer.BlockCopy (num, 0, oid, j, num.Length);
- j += num.Length;
- }
- else
- oid[j++] = Convert.ToByte (x);
- }
-
- int k = 2;
- // copy the exact number of byte required
- byte[] oid2 = new byte [j];
- oid2[0] = 0x06; // always - this tag means OID
- // Length (of value)
- if (j > 0x7F) {
- // for compatibility with MS BCL
- throw new CryptographicUnexpectedOperationException (
- Locale.GetText ("OID > 127 bytes"));
- // comment exception and uncomment next 3 lines to remove restriction
- //byte[] num = EncodeLongNumber (j);
- //Buffer.BlockCopy (num, 0, oid, j, num.Length);
- //k = num.Length + 1;
- }
- else
- oid2 [1] = Convert.ToByte (j - 2);
-
- Buffer.BlockCopy (oid, k, oid2, k, j - k);
- return oid2;
- }
-
- // encode (7bits array) number greater than 127
- private static byte[] EncodeLongNumber (long x)
- {
- // for MS BCL compatibility
- // comment next two lines to remove restriction
- if ((x > Int32.MaxValue) || (x < Int32.MinValue))
- throw new OverflowException (Locale.GetText ("Part of OID doesn't fit in Int32"));
-
- long y = x;
- // number of bytes required to encode this number
- int n = 1;
- while (y > 0x7F) {
- y = y >> 7;
- n++;
- }
- byte[] num = new byte [n];
- // encode all bytes
- for (int i = 0; i < n; i++) {
- y = x >> (7 * i);
- y = y & 0x7F;
- if (i != 0)
- y += 0x80;
- num[n-i-1] = Convert.ToByte (y);
- }
- return num;
- }
-
- [MonoLimitation ("nothing is FIPS certified so it never make sense to restrict to this (empty) subset")]
- public static bool AllowOnlyFipsAlgorithms {
- get { return false; }
- }
- }
-}
-
if (url.Length == 0)
return new Zone (z);
- Uri uri = new Uri (url);
+ Uri uri = null;
+ try {
+ uri = new Uri (url);
+ }
+ catch {
+ return new Zone (z);
+ }
// TODO: apply zone configuration
// this is the only way to use the Trusted and Untrusted zones
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)
+++ /dev/null
-//
-// System.Threading.EventWaitHandle.cs
-//
-// Author:
-// Dick Porter (dick@ximian.com)
-//
-// (C) Ximian, Inc. (http://www.ximian.com)
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Security.AccessControl;
-
-namespace System.Threading
-{
- [ComVisible (true)]
- public class EventWaitHandle : WaitHandle
- {
- private EventWaitHandle (IntPtr handle)
- {
- Handle = handle;
- }
-
- static bool IsManualReset (EventResetMode mode)
- {
- if ((mode < EventResetMode.AutoReset) || (mode > EventResetMode.ManualReset))
- throw new ArgumentException ("mode");
- return (mode == EventResetMode.ManualReset);
- }
-
- public EventWaitHandle (bool initialState, EventResetMode mode)
- {
- bool created;
- bool manual = IsManualReset (mode);
- Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, null, out created);
- }
-
-#if !MOBILE
-
- public EventWaitHandle (bool initialState, EventResetMode mode,
- string name)
- {
- bool created;
- bool manual = IsManualReset (mode);
- Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out created);
- }
-
- public EventWaitHandle (bool initialState, EventResetMode mode,
- string name, out bool createdNew)
- {
- bool manual = IsManualReset (mode);
- Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out createdNew);
- }
-
-
- [MonoTODO ("Use access control in CreateEvent_internal")]
- public EventWaitHandle (bool initialState, EventResetMode mode,
- string name, out bool createdNew,
- EventWaitHandleSecurity eventSecurity)
- {
- bool manual = IsManualReset (mode);
- Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out createdNew);
- }
-
- public EventWaitHandleSecurity GetAccessControl ()
- {
- return new EventWaitHandleSecurity (SafeWaitHandle,
- AccessControlSections.Owner |
- AccessControlSections.Group |
- AccessControlSections.Access);
-
- }
-
- public static EventWaitHandle OpenExisting (string name)
- {
- return(OpenExisting (name, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify));
- }
-
- public static EventWaitHandle OpenExisting (string name, EventWaitHandleRights rights)
- {
- if (name == null) {
- throw new ArgumentNullException ("name");
- }
- if ((name.Length == 0) ||
- (name.Length > 260)) {
- throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260]."));
- }
-
- MonoIOError error;
- IntPtr handle = NativeEventCalls.OpenEvent_internal (name, rights, out error);
- if (handle == (IntPtr)null) {
- if (error == MonoIOError.ERROR_FILE_NOT_FOUND) {
- throw new WaitHandleCannotBeOpenedException (Locale.GetText ("Named Event handle does not exist: ") + name);
- } else if (error == MonoIOError.ERROR_ACCESS_DENIED) {
- throw new UnauthorizedAccessException ();
- } else {
- throw new IOException (Locale.GetText ("Win32 IO error: ") + error.ToString ());
- }
- }
-
- return(new EventWaitHandle (handle));
- }
-
- public static bool TryOpenExisting (string name, out EventWaitHandle result)
- {
- return TryOpenExisting (
- name, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify, out result);
- }
-
- public static bool TryOpenExisting (string name, EventWaitHandleRights rights,
- out EventWaitHandle result)
- {
- if (name == null) {
- throw new ArgumentNullException ("name");
- }
- if ((name.Length == 0) || (name.Length > 260)) {
- throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260]."));
- }
-
- MonoIOError error;
- IntPtr handle = NativeEventCalls.OpenEvent_internal (name, rights, out error);
- if (handle == (IntPtr)null) {
- result = null;
- return false;
- }
-
- result = new EventWaitHandle (handle);
- return true;
- }
-#else
- public EventWaitHandle (bool initialState, EventResetMode mode, string name)
- {
- throw new NotSupportedException ();
- }
-
- public EventWaitHandle (bool initialState, EventResetMode mode,
- string name, out bool createdNew)
- {
- throw new NotSupportedException ();
- }
-
-
- public EventWaitHandle (bool initialState, EventResetMode mode,
- string name, out bool createdNew,
- EventWaitHandleSecurity eventSecurity)
- {
- throw new NotSupportedException ();
- }
-
- public static EventWaitHandle OpenExisting (string name)
- {
- throw new NotSupportedException ();
- }
-
- public static EventWaitHandle OpenExisting (string name, EventWaitHandleRights rights)
- {
- throw new NotSupportedException ();
- }
-
- public static bool TryOpenExisting (string name, out EventWaitHandle result)
- {
- throw new NotSupportedException ();
- }
-
- public static bool TryOpenExisting (string name, EventWaitHandleRights rights,
- out EventWaitHandle result)
- {
- throw new NotSupportedException ();
- }
-#endif
-
- public bool Reset ()
- {
- /* This needs locking since another thread could dispose the handle */
- lock (this) {
- CheckDisposed ();
-
- return NativeEventCalls.ResetEvent (SafeWaitHandle);
- }
- }
-
- public bool Set ()
- {
- lock (this) {
- CheckDisposed ();
-
- return NativeEventCalls.SetEvent (SafeWaitHandle);
- }
- }
-
- internal void CheckDisposed ()
- {
- if (disposed)
- throw new ObjectDisposedException (GetType ().FullName);
- }
-
- bool disposed;
- protected override void Dispose(bool explicitDisposing)
- {
- base.Dispose (explicitDisposing);
- disposed = true;
- }
-
-#if !MOBILE
- public void SetAccessControl (EventWaitHandleSecurity eventSecurity)
- {
- if (null == eventSecurity)
- throw new ArgumentNullException ("eventSecurity");
-
- eventSecurity.PersistModifications (SafeWaitHandle);
-
- }
-#endif
- }
-}
internal static class NativeEventCalls
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- public static extern IntPtr CreateEvent_internal(bool manual,bool initial,string name, out bool created);
+ public static extern IntPtr CreateEvent_internal (bool manual, bool initial, string name, out int errorCode);
public static bool SetEvent (SafeWaitHandle handle)
{
#if !MOBILE
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- public static extern IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out MonoIOError error);
+ public static extern IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out int errorCode);
#endif
}
}
/* start_notify is used by the runtime to signal that Start()
* is ok to return
*/
- private IntPtr start_notify;
private IntPtr stack_ptr;
private UIntPtr static_data; /* GC-tracked */
private IntPtr runtime_thread_info;
private IntPtr interrupt_on_stop;
private IntPtr flags;
private IntPtr thread_pinning_ref;
+ private IntPtr abort_protected_block_count;
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to the unmanaged MonoThread structure.
IPrincipal principal;
int principal_version;
- bool current_culture_set;
- bool current_ui_culture_set;
- CultureInfo current_culture;
- CultureInfo current_ui_culture;
// the name of current_thread is
// important because they are used by the runtime.
[ThreadStatic]
static Thread current_thread;
- static internal CultureInfo default_culture;
- static internal CultureInfo default_ui_culture;
-
// can be both a ThreadStart and a ParameterizedThreadStart
private MulticastDelegate m_Delegate;
}
}
- //[MethodImplAttribute (MethodImplOptions.InternalCall)]
- //private static extern int current_lcid ();
-
- public CultureInfo CurrentCulture {
- get {
- CultureInfo culture = current_culture;
- if (current_culture_set && culture != null)
- return culture;
-
- if (default_culture != null)
- return default_culture;
-
- current_culture = culture = CultureInfo.ConstructCurrentCulture ();
- return culture;
- }
-
- [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
- set {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- value.CheckNeutral ();
- current_culture = value;
- current_culture_set = true;
- }
- }
-
- public CultureInfo CurrentUICulture {
- get {
- CultureInfo culture = current_ui_culture;
- if (current_ui_culture_set && culture != null)
- return culture;
-
- if (default_ui_culture != null)
- return default_ui_culture;
-
- current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
- return culture;
- }
-
- set {
- if (value == null)
- throw new ArgumentNullException ("value");
- current_ui_culture = value;
- current_ui_culture_set = true;
- }
- }
-
public bool IsThreadPoolThread {
get {
return IsThreadPoolThreadInternal;
return ManagedThreadId;
}
- internal CultureInfo GetCurrentUICultureNoAppX ()
- {
- return CultureInfo.CurrentUICulture;
- }
-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
+using System.Security.Permissions;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Hosting;
appBase = appBase.Substring (7);
if (Path.DirectorySeparatorChar != '/')
appBase = appBase.Replace ('/', Path.DirectorySeparatorChar);
- if (Environment.IsRunningOnWindows) {
- // Under Windows prepend "//" to indicate it's a local file
- appBase = "//" + appBase;
+ }
+ appBase = Path.GetFullPath (appBase);
+
+ if (Path.DirectorySeparatorChar != '/') {
+ bool isExtendedPath = appBase.StartsWith (@"\\?\", StringComparison.Ordinal);
+ if (appBase.IndexOf (':', isExtendedPath ? 6 : 2) != -1) {
+ throw new NotSupportedException ("The given path's format is not supported.");
}
- } else {
- appBase = Path.GetFullPath (appBase);
+ }
+
+ // validate the path
+ string dir = Path.GetDirectoryName (appBase);
+ if ((dir != null) && (dir.LastIndexOfAny (Path.GetInvalidPathChars ()) >= 0)) {
+ string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), appBase);
+ throw new ArgumentException (msg, "appBase");
+ }
+
+ string fname = Path.GetFileName (appBase);
+ if ((fname != null) && (fname.LastIndexOfAny (Path.GetInvalidFileNameChars ()) >= 0)) {
+ string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), appBase);
+ throw new ArgumentException (msg, "appBase");
}
return appBase;
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 152;
+ private const int mono_corlib_version = 154;
#pragma warning restore 169
[ComVisible (true)]
public extern static string[] GetCommandLineArgs ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern static string internalGetEnvironmentVariable (string variable);
+ internal extern static string internalGetEnvironmentVariable_native (IntPtr variable);
+
+ internal static string internalGetEnvironmentVariable (string variable) {
+ if (variable == null)
+ return null;
+ using (var h = Mono.RuntimeMarshal.MarshalString (variable)) {
+ return internalGetEnvironmentVariable_native (h.Value);
+ }
+ }
/// <summary>
/// Return a string containing the value of the environment
}
}
#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)
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);
[SecurityCritical]
public static void FailFast (string message, Exception exception)
{
- throw new NotImplementedException ();
+#pragma warning disable 618
+ throw new ExecutionEngineException (message, exception);
+#pragma warning restore
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public static DateTime ConvertTimeBySystemTimeZoneId (DateTime dateTime, string sourceTimeZoneId, string destinationTimeZoneId)
{
- return ConvertTime (dateTime, FindSystemTimeZoneById (sourceTimeZoneId), FindSystemTimeZoneById (destinationTimeZoneId));
+ TimeZoneInfo source_tz;
+ if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZoneId == TimeZoneInfo.Utc.Id) {
+ source_tz = Utc;
+ } else {
+ source_tz = FindSystemTimeZoneById (sourceTimeZoneId);
+ }
+
+ return ConvertTime (dateTime, source_tz, FindSystemTimeZoneById (destinationTimeZoneId));
}
public static DateTimeOffset ConvertTimeBySystemTimeZoneId (DateTimeOffset dateTimeOffset, string destinationTimeZoneId)
subkey.Close ();
if (key != null)
key.Close ();
+ Registry.CurrentUser.DeleteSubKeyTree (subKeyName, false);
}
}
subkey.Close ();
if (key != null)
key.Close ();
+ Registry.CurrentUser.DeleteSubKeyTree (subKeyName, false);
}
}
RegistryKey key = null;
RegistryKey key2 = null;
RegistryKey subkey = null;
- string subKeyName = "VolatileKey";
+ string subKeyNameVolatile = "VolatileKey";
+ string subKeyNameNonVolatile = "NonVolatileKey";
try {
//
// Create a volatile key and try to open it as a normal one
//
- key = Registry.CurrentUser.CreateSubKey (subKeyName, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
- key2 = Registry.CurrentUser.CreateSubKey (subKeyName, RegistryKeyPermissionCheck.Default, RegistryOptions.None);
+ key = Registry.CurrentUser.CreateSubKey (subKeyNameVolatile, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
+ key2 = Registry.CurrentUser.CreateSubKey (subKeyNameVolatile, RegistryKeyPermissionCheck.Default, RegistryOptions.None);
Assert.AreEqual (key.Name, key2.Name, "A0");
subkey = key2.CreateSubKey ("Child", RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
//
// Create a non-volatile key and try to open it as a volatile one
//
- subKeyName = "NonVolatileKey";
- key2 = Registry.CurrentUser.CreateSubKey (subKeyName, RegistryKeyPermissionCheck.Default, RegistryOptions.None);
+ key2 = Registry.CurrentUser.CreateSubKey (subKeyNameNonVolatile, RegistryKeyPermissionCheck.Default, RegistryOptions.None);
key2.SetValue ("Name", "Mono");
- key = Registry.CurrentUser.CreateSubKey (subKeyName, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
+ key = Registry.CurrentUser.CreateSubKey (subKeyNameNonVolatile, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
Assert.AreEqual (key.Name, key2.Name, "B0");
Assert.AreEqual ("Mono", key.GetValue ("Name"), "#B1");
Assert.AreEqual ("Mono", key2.GetValue ("Name"), "#B2");
//
key.Close ();
key2.Close ();
- key = Registry.CurrentUser.CreateSubKey (subKeyName, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
+ key = Registry.CurrentUser.CreateSubKey (subKeyNameNonVolatile, RegistryKeyPermissionCheck.Default, RegistryOptions.Volatile);
Assert.AreEqual ("Mono", key.GetValue ("Name"), "#C0");
Assert.AreEqual (true, key.OpenSubKey ("Child") != null, "#C1");
} finally {
key.Close ();
if (key2 != null)
key2.Close ();
+ Registry.CurrentUser.DeleteSubKeyTree (subKeyNameVolatile, false);
+ Registry.CurrentUser.DeleteSubKeyTree (subKeyNameNonVolatile, false);
}
}
}
}
-#if NET_4_5
[Test]
public void Create ()
{
} catch (ArgumentNullException) {
}
}
-#endif
[Test]
public void DefaultComparer_UserComparable ()
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
+using System.Threading.Tasks;
using NUnit.Framework;
Assert.IsFalse (zh2.Equals (zh1), "#2");
}
-#if NET_4_5
CountdownEvent barrier = new CountdownEvent (3);
AutoResetEvent[] evt = new AutoResetEvent [] { new AutoResetEvent (false), new AutoResetEvent (false), new AutoResetEvent (false), new AutoResetEvent (false)};
}
[Test]
- public void DefaultThreadCurrentCultureAndNumberFormaters () {
+ public void DefaultThreadCurrentCultureIsIgnoredWhenCultureFlowsToThread ()
+ {
string us_str = null;
string br_str = null;
+
var thread = new Thread (() => {
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
us_str = 100000.ToString ("C");
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-BR");
br_str = 100000.ToString ("C");
});
+
+ var expected = 100000.ToString ("C");
+
thread.Start ();
- thread.Join ();
+ Assert.IsTrue (thread.Join (5000), "#0");
CultureInfo.DefaultThreadCurrentCulture = null;
- Assert.AreEqual ("$100,000.00", us_str, "#1");
- Assert.AreEqual ("R$ 100.000,00", br_str, "#2");
+ Assert.AreEqual (expected, us_str, "#1");
+ Assert.AreEqual (expected, br_str, "#2");
+ }
+
+ [Test]
+ public void FlowCultureInfoFromParentThreadSinceNet46 ()
+ {
+ Func<Task> f = async () => {
+ Thread.CurrentThread.CurrentUICulture = new CultureInfo ("pt-BR");
+ await Task.Yield ();
+ Assert.AreEqual ("pt-BR", Thread.CurrentThread.CurrentUICulture.Name);
+ };
+
+ f ().Wait ();
}
-#endif
}
}
info = new DirectoryInfo ("/test/");
Assert.AreEqual ("test", info.Name, "#4");
} else {
+ Directory.SetCurrentDirectory (@"C:\");
+
info = new DirectoryInfo (@"c:");
Assert.AreEqual (@"C:\", info.Name, "#4");
Assert.IsNotNull (info.Parent, "#7a");
Assert.AreEqual ("/", info.Parent.FullName, "#7b");
} else {
+ Directory.SetCurrentDirectory (@"C:\");
+
info = new DirectoryInfo (@"c:");
Assert.IsNull (info.Parent, "#4");
di = new DirectoryInfo ("/test/");
Assert.AreEqual ("/test/", di.FullName, "#D4");
} else {
+ Directory.SetCurrentDirectory (@"C:\");
+
di = new DirectoryInfo (@"c:");
Assert.AreEqual (@"C:\", di.FullName, "#D1");
try {
info.MoveTo (destFile);
Assert.Fail ("#1");
- } catch (FileNotFoundException ex) {
+ } catch (DirectoryNotFoundException ex) {
// Could not find a part of the path
- Assert.AreEqual (typeof (FileNotFoundException), ex.GetType (), "#2");
+ Assert.AreEqual (typeof (DirectoryNotFoundException), ex.GetType (), "#2");
Assert.IsNull (ex.InnerException, "#3");
Assert.IsNotNull (ex.Message, "#4");
}
{
string TempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.IO.Tests");
static readonly char DSC = Path.DirectorySeparatorChar;
- static bool MacOSX = false;
-
- [DllImport ("libc")]
- static extern int uname (IntPtr buf);
[TearDown]
public void TearDown ()
Directory.Delete (TempFolder, true);
Directory.CreateDirectory (TempFolder);
-#if !MOBILE
- // from XplatUI.cs
- IntPtr buf = Marshal.AllocHGlobal (8192);
- if (uname (buf) == 0)
- MacOSX = Marshal.PtrToStringAnsi (buf) == "Darwin";
- Marshal.FreeHGlobal (buf);
-#endif
}
public void TestCtr ()
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
-#if NET_4_5
using System.Threading.Tasks;
-#endif
using NUnit.Framework;
Assert.IsTrue (ms.DisposedCalled, "After");
}
-#if NET_4_5
[Test]
public void ReadAsync ()
{
return true;
}
}
-#endif
}
}
static string path3;
static OsType OS;
static char DSC = Path.DirectorySeparatorChar;
+ static char ADSC = Path.AltDirectorySeparatorChar;
[SetUp]
public void SetUp ()
}
}
+ [Test]
+ public void GetDirectoryName_Replaces_AltDirectorySeparatorChar ()
+ {
+ Assert.AreEqual ($"foo{DSC}bar", Path.GetDirectoryName ($"foo{ADSC}bar{ADSC}dingus"), "#1");
+ }
+
[Test]
public void GetExtension ()
{
using System;
using System.IO;
using System.Text;
-#if NET_4_5
using System.Threading.Tasks;
-#endif
using NUnit.Framework;
Assert.AreEqual (0, StreamReader.Null.ReadBlock (buffer, 0, buffer.Length));
}
-#if NET_4_5
[Test]
public void ReadLineAsync ()
{
Assert.IsTrue (result.Wait (3000), "#1");
Assert.AreEqual ("ab" + Environment.NewLine, result.Result);
}
-#endif
}
class MyStream : Stream {
Assert.IsFalse (s.CanRead, "#1");
}
-#if NET_4_5
[Test]
public void CopyAsync ()
{
} catch (AggregateException) {
}
}
-#endif
}
}
Assert.AreEqual (5, ms.Position, "#2");
}
-#if NET_4_5
[Test]
public void FlushAsync ()
{
Assert.IsTrue (t.Wait (1000), "#5");
}
-#endif
// TODO - Write - test errors, functionality tested in TestFlush.
}
Assert.IsNull (an.GetPublicKey (), "GetPublicKey");
Assert.IsNull (an.GetPublicKeyToken (), "GetPublicKeyToken");
Assert.AreEqual ("TestAssembly", an.ToString (), "ToString");
-#if NET_4_5
Assert.IsNull (an.CultureName, "CultureName");
Assert.AreEqual (AssemblyContentType.Default, an.ContentType, "ContentType");
-#endif
}
[Test] // ctor (String)
[TestFixture]
public class AssemblyTest
{
- static string TempFolder = Path.Combine (Path.GetTempPath (),
+ static string BaseTempFolder = Path.Combine (Path.GetTempPath (),
"MonoTests.System.Reflection.AssemblyTest");
+ static string TempFolder;
+
+ [TestFixtureSetUp]
+ public void FixtureSetUp ()
+ {
+ try {
+ // Try to cleanup from any previous NUnit run.
+ Directory.Delete (BaseTempFolder, true);
+ } catch (Exception) {
+ }
+ }
[SetUp]
public void SetUp ()
{
- while (Directory.Exists (TempFolder))
- TempFolder = Path.Combine (TempFolder, "2");
+ int i = 0;
+ do {
+ TempFolder = Path.Combine (BaseTempFolder, (++i).ToString());
+ } while (Directory.Exists (TempFolder));
Directory.CreateDirectory (TempFolder);
}
public void TearDown ()
{
try {
- // This throws an exception under MS.NET, since the directory contains loaded
- // assemblies.
+ // This throws an exception under MS.NET and Mono on Windows,
+ // since the directory contains loaded assemblies.
Directory.Delete (TempFolder, true);
} catch (Exception) {
}
[Test] // bug #78517
public void LoadFrom_Empty_Assembly ()
{
- string tempFile = Path.GetTempFileName ();
+ string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ());
+ File.CreateText (tempFile).Close ();
try {
Assembly.LoadFrom (tempFile);
Assert.Fail ("#1");
} catch (BadImageFormatException ex) {
Assert.IsNull (ex.InnerException, "#2");
- } finally {
- File.Delete (tempFile);
}
}
[Test] // bug #78517
public void LoadFrom_Invalid_Assembly ()
{
- string tempFile = Path.GetTempFileName ();
+ string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ());
using (StreamWriter sw = File.CreateText (tempFile)) {
sw.WriteLine ("foo");
sw.Close ();
Assert.Fail ("#1");
} catch (BadImageFormatException ex) {
Assert.IsNull (ex.InnerException, "#2");
- } finally {
- File.Delete (tempFile);
}
}
[Test]
public void LoadFrom_NonExisting_Assembly ()
{
- string tempFile = Path.GetTempFileName ();
- File.Delete (tempFile);
+ string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ());
try {
Assembly.LoadFrom (tempFile);
Assert.Fail ("#1");
} catch (FileNotFoundException ex) {
Assert.IsNull (ex.InnerException, "#2");
- } finally {
- File.Delete (tempFile);
}
}
[Test]
public void Location_Empty() {
string assemblyFileName = Path.Combine (
- Path.GetTempPath (), "AssemblyLocation.dll");
-
- try {
- AssemblyName assemblyName = new AssemblyName ();
- assemblyName.Name = "AssemblyLocation";
-
- AssemblyBuilder ab = AppDomain.CurrentDomain
- .DefineDynamicAssembly (assemblyName,
- AssemblyBuilderAccess.Save,
- Path.GetTempPath (),
- AppDomain.CurrentDomain.Evidence);
- ab.Save (Path.GetFileName (assemblyFileName));
-
- using (FileStream fs = File.OpenRead (assemblyFileName)) {
- byte[] buffer = new byte[fs.Length];
- fs.Read (buffer, 0, buffer.Length);
- Assembly assembly = Assembly.Load (buffer);
- Assert.AreEqual (string.Empty, assembly.Location);
- fs.Close ();
- }
- } finally {
- File.Delete (assemblyFileName);
+ TempFolder, "AssemblyLocation.dll");
+
+ AssemblyName assemblyName = new AssemblyName ();
+ assemblyName.Name = "AssemblyLocation";
+
+ AssemblyBuilder ab = AppDomain.CurrentDomain
+ .DefineDynamicAssembly (assemblyName,
+ AssemblyBuilderAccess.Save,
+ TempFolder,
+ AppDomain.CurrentDomain.Evidence);
+ ab.Save (Path.GetFileName (assemblyFileName));
+
+ using (FileStream fs = File.OpenRead (assemblyFileName)) {
+ byte[] buffer = new byte[fs.Length];
+ fs.Read (buffer, 0, buffer.Length);
+ Assembly assembly = Assembly.Load (buffer);
+ Assert.AreEqual (string.Empty, assembly.Location);
+ fs.Close ();
}
}
public void SateliteAssemblyForInMemoryAssembly ()
{
string assemblyFileName = Path.Combine (
- Path.GetTempPath (), "AssemblyLocation1.dll");
+ TempFolder, "AssemblyLocation1.dll");
- try {
- AssemblyName assemblyName = new AssemblyName ();
- assemblyName.Name = "AssemblyLocation1";
-
- AssemblyBuilder ab = AppDomain.CurrentDomain
- .DefineDynamicAssembly (assemblyName,
- AssemblyBuilderAccess.Save,
- Path.GetTempPath ());
+ AssemblyName assemblyName = new AssemblyName ();
+ assemblyName.Name = "AssemblyLocation1";
- ModuleBuilder moduleBuilder = ab.DefineDynamicModule (assemblyName.Name, assemblyName.Name + ".dll");
- TypeBuilder typeBuilder = moduleBuilder.DefineType ("Program", TypeAttributes.Public);
+ AssemblyBuilder ab = AppDomain.CurrentDomain
+ .DefineDynamicAssembly (assemblyName,
+ AssemblyBuilderAccess.Save,
+ TempFolder);
- MethodBuilder methodBuilder = typeBuilder.DefineMethod ("TestCall", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes);
- ILGenerator gen = methodBuilder.GetILGenerator ();
+ ModuleBuilder moduleBuilder = ab.DefineDynamicModule (assemblyName.Name, assemblyName.Name + ".dll");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType ("Program", TypeAttributes.Public);
- //
- // var resourceManager = new ResourceManager (typeof (Program));
- // resourceManager.GetString ("test");
- //
- gen.Emit (OpCodes.Ldtoken, typeBuilder);
- gen.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
- gen.Emit (OpCodes.Newobj, typeof(ResourceManager).GetConstructor (new Type[] { typeof(Type) }));
- gen.Emit (OpCodes.Ldstr, "test");
- gen.Emit (OpCodes.Callvirt, typeof(ResourceManager).GetMethod ("GetString", new Type[] { typeof(string) }));
- gen.Emit (OpCodes.Pop);
- gen.Emit (OpCodes.Ret);
+ MethodBuilder methodBuilder = typeBuilder.DefineMethod ("TestCall", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes);
+ ILGenerator gen = methodBuilder.GetILGenerator ();
- typeBuilder.CreateType ();
+ //
+ // var resourceManager = new ResourceManager (typeof (Program));
+ // resourceManager.GetString ("test");
+ //
+ gen.Emit (OpCodes.Ldtoken, typeBuilder);
+ gen.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
+ gen.Emit (OpCodes.Newobj, typeof(ResourceManager).GetConstructor (new Type[] { typeof(Type) }));
+ gen.Emit (OpCodes.Ldstr, "test");
+ gen.Emit (OpCodes.Callvirt, typeof(ResourceManager).GetMethod ("GetString", new Type[] { typeof(string) }));
+ gen.Emit (OpCodes.Pop);
+ gen.Emit (OpCodes.Ret);
- ab.Save (Path.GetFileName (assemblyFileName));
+ typeBuilder.CreateType ();
- using (FileStream fs = File.OpenRead (assemblyFileName)) {
- byte[] buffer = new byte[fs.Length];
- fs.Read (buffer, 0, buffer.Length);
- Assembly assembly = Assembly.Load (buffer);
+ ab.Save (Path.GetFileName (assemblyFileName));
- var mm = assembly.GetType ("Program").GetMethod ("TestCall");
- try {
- mm.Invoke (null, null);
- Assert.Fail ();
- } catch (TargetInvocationException e) {
- Assert.IsTrue (e.InnerException is MissingManifestResourceException);
- }
+ using (FileStream fs = File.OpenRead (assemblyFileName)) {
+ byte[] buffer = new byte[fs.Length];
+ fs.Read (buffer, 0, buffer.Length);
+ Assembly assembly = Assembly.Load (buffer);
- fs.Close ();
+ var mm = assembly.GetType ("Program").GetMethod ("TestCall");
+ try {
+ mm.Invoke (null, null);
+ Assert.Fail ();
+ } catch (TargetInvocationException e) {
+ Assert.IsTrue (e.InnerException is MissingManifestResourceException);
}
- } finally {
- File.Delete (assemblyFileName);
+
+ fs.Close ();
}
}
public void bug78464 ()
{
string assemblyFileName = Path.Combine (
- Path.GetTempPath (), "bug78464.dll");
+ TempFolder, "bug78464.dll");
+ // execute test in separate appdomain to allow assembly to be unloaded
+ AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
+ CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
try {
- // execute test in separate appdomain to allow assembly to be unloaded
- AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
- CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
- try {
- crossDomainTester.bug78464 (assemblyFileName);
- } finally {
- AppDomain.Unload (testDomain);
- }
+ crossDomainTester.bug78464 (assemblyFileName);
} finally {
- File.Delete (assemblyFileName);
+ AppDomain.Unload (testDomain);
}
}
public void bug78465 ()
{
string assemblyFileName = Path.Combine (
- Path.GetTempPath (), "bug78465.dll");
+ TempFolder, "bug78465.dll");
+
+ AssemblyName assemblyName = new AssemblyName ();
+ assemblyName.Name = "bug78465";
+
+ AssemblyBuilder ab = AppDomain.CurrentDomain
+ .DefineDynamicAssembly (assemblyName,
+ AssemblyBuilderAccess.Save,
+ Path.GetDirectoryName (assemblyFileName),
+ AppDomain.CurrentDomain.Evidence);
+ ab.Save (Path.GetFileName (assemblyFileName));
+
+ using (FileStream fs = File.OpenRead (assemblyFileName)) {
+ byte[] buffer = new byte[fs.Length];
+ fs.Read (buffer, 0, buffer.Length);
+ Assembly assembly = Assembly.Load (buffer);
+ Assert.AreEqual (string.Empty, assembly.Location, "#1");
+ fs.Close ();
+ }
+ AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
+ CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
try {
- AssemblyName assemblyName = new AssemblyName ();
- assemblyName.Name = "bug78465";
-
- AssemblyBuilder ab = AppDomain.CurrentDomain
- .DefineDynamicAssembly (assemblyName,
- AssemblyBuilderAccess.Save,
- Path.GetDirectoryName (assemblyFileName),
- AppDomain.CurrentDomain.Evidence);
- ab.Save (Path.GetFileName (assemblyFileName));
-
- using (FileStream fs = File.OpenRead (assemblyFileName)) {
- byte[] buffer = new byte[fs.Length];
- fs.Read (buffer, 0, buffer.Length);
- Assembly assembly = Assembly.Load (buffer);
- Assert.AreEqual (string.Empty, assembly.Location, "#1");
- fs.Close ();
- }
-
- AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
- CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
- try {
- crossDomainTester.bug78465 (assemblyFileName);
- } finally {
- AppDomain.Unload (testDomain);
- }
+ crossDomainTester.bug78465 (assemblyFileName);
} finally {
- File.Delete (assemblyFileName);
+ AppDomain.Unload (testDomain);
}
}
[Category("MobileNotWorking")]
public void bug78468 ()
{
- string assemblyFileNameA = Path.Combine (Path.GetTempPath (),
+ string assemblyFileNameA = Path.Combine (TempFolder,
"bug78468a.dll");
- string resourceFileName = Path.Combine (Path.GetTempPath (),
+ string resourceFileName = Path.Combine (TempFolder,
"readme.txt");
using (StreamWriter sw = File.CreateText (resourceFileName)) {
sw.Close ();
}
- try {
- AssemblyName assemblyName = new AssemblyName ();
- assemblyName.Name = "bug78468a";
+ AssemblyName assemblyName = new AssemblyName ();
+ assemblyName.Name = "bug78468a";
- AssemblyBuilder ab = AppDomain.CurrentDomain
- .DefineDynamicAssembly (assemblyName,
- AssemblyBuilderAccess.Save,
- Path.GetTempPath (),
- AppDomain.CurrentDomain.Evidence);
- ab.AddResourceFile ("read", "readme.txt");
- ab.Save (Path.GetFileName (assemblyFileNameA));
+ AssemblyBuilder ab = AppDomain.CurrentDomain
+ .DefineDynamicAssembly (assemblyName,
+ AssemblyBuilderAccess.Save,
+ TempFolder,
+ AppDomain.CurrentDomain.Evidence);
+ ab.AddResourceFile ("read", "readme.txt");
+ ab.Save (Path.GetFileName (assemblyFileNameA));
- Assembly assembly;
+ Assembly assembly;
- using (FileStream fs = File.OpenRead (assemblyFileNameA)) {
- byte[] buffer = new byte[fs.Length];
- fs.Read (buffer, 0, buffer.Length);
- assembly = Assembly.Load (buffer);
- fs.Close ();
- }
+ using (FileStream fs = File.OpenRead (assemblyFileNameA)) {
+ byte[] buffer = new byte[fs.Length];
+ fs.Read (buffer, 0, buffer.Length);
+ assembly = Assembly.Load (buffer);
+ fs.Close ();
+ }
- Assert.AreEqual (string.Empty, assembly.Location, "#A1");
- string[] resNames = assembly.GetManifestResourceNames ();
- Assert.IsNotNull (resNames, "#A2");
- Assert.AreEqual (1, resNames.Length, "#A3");
- Assert.AreEqual ("read", resNames[0], "#A4");
- ManifestResourceInfo resInfo = assembly.GetManifestResourceInfo ("read");
- Assert.IsNotNull (resInfo, "#A5");
- Assert.AreEqual ("readme.txt", resInfo.FileName, "#A6");
- Assert.IsNull (resInfo.ReferencedAssembly, "#A7");
- Assert.AreEqual ((ResourceLocation) 0, resInfo.ResourceLocation, "#A8");
- try {
- assembly.GetManifestResourceStream ("read");
- Assert.Fail ("#A9");
- } catch (FileNotFoundException) {
- }
- try {
- assembly.GetFile ("readme.txt");
- Assert.Fail ("#A10");
- } catch (FileNotFoundException) {
- }
+ Assert.AreEqual (string.Empty, assembly.Location, "#A1");
+ string[] resNames = assembly.GetManifestResourceNames ();
+ Assert.IsNotNull (resNames, "#A2");
+ Assert.AreEqual (1, resNames.Length, "#A3");
+ Assert.AreEqual ("read", resNames[0], "#A4");
+ ManifestResourceInfo resInfo = assembly.GetManifestResourceInfo ("read");
+ Assert.IsNotNull (resInfo, "#A5");
+ Assert.AreEqual ("readme.txt", resInfo.FileName, "#A6");
+ Assert.IsNull (resInfo.ReferencedAssembly, "#A7");
+ Assert.AreEqual ((ResourceLocation) 0, resInfo.ResourceLocation, "#A8");
+ try {
+ assembly.GetManifestResourceStream ("read");
+ Assert.Fail ("#A9");
+ } catch (FileNotFoundException) {
+ }
+ try {
+ assembly.GetFile ("readme.txt");
+ Assert.Fail ("#A10");
+ } catch (FileNotFoundException) {
+ }
- string assemblyFileNameB = Path.Combine (Path.GetTempPath (),
- "bug78468b.dll");
+ string assemblyFileNameB = Path.Combine (TempFolder,
+ "bug78468b.dll");
- AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
- CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
- try {
- crossDomainTester.bug78468 (assemblyFileNameB);
- } finally {
- AppDomain.Unload (testDomain);
- File.Delete (assemblyFileNameB);
- }
+ AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false);
+ CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain);
+ try {
+ crossDomainTester.bug78468 (assemblyFileNameB);
} finally {
- File.Delete (assemblyFileNameA);
- File.Delete (resourceFileName);
+ AppDomain.Unload (testDomain);
}
}
[Category ("NotWorking")] // patch for bug #79720 must be committed first
public void Load_Culture ()
{
- string tempDir = Path.Combine (Path.GetTempPath (),
- "MonoTests.System.Reflection.AssemblyTest");
+ string tempDir = TempFolder;
string cultureTempDir = Path.Combine (tempDir, "nl-BE");
if (!Directory.Exists (cultureTempDir))
Directory.CreateDirectory (cultureTempDir);
Assert.IsTrue (cdt.AssertFileNotFoundException (aname), "#D3");
} finally {
AppDomain.Unload (ad);
- if (Directory.Exists (tempDir))
- Directory.Delete (tempDir, true);
}
}
[Category ("NotWorking")] // in non-default domain, MS throws FileNotFoundException
public void Load_Culture_Mismatch ()
{
- string tempDir = Path.Combine (Path.GetTempPath (),
- "MonoTests.System.Reflection.AssemblyTest");
+ string tempDir = TempFolder;
string cultureTempDir = Path.Combine (tempDir, "en-US");
if (!Directory.Exists (cultureTempDir))
Directory.CreateDirectory (cultureTempDir);
Assert.IsTrue (cdt.AssertFileNotFoundException (aname), "#B1");
} finally {
AppDomain.Unload (ad);
- if (Directory.Exists (tempDir))
- Directory.Delete (tempDir, true);
}
}
[Category("MobileNotWorking")]
public void Load_PartialVersion ()
{
- string tempDir = Path.Combine (Path.GetTempPath (),
- "MonoTests.System.Reflection.AssemblyTest");
- if (!Directory.Exists (tempDir))
- Directory.CreateDirectory (tempDir);
+ string tempDir = TempFolder;
AppDomain ad = CreateTestDomain (tempDir, true);
try {
Assert.IsTrue (cdt.AssertLoad (aname.FullName), "#C2");
} finally {
AppDomain.Unload (ad);
- if (Directory.Exists (tempDir))
- Directory.Delete (tempDir, true);
}
}
[Test]
public void bug79872 ()
{
- Random rnd = new Random ();
- string outdir;
- int tries = 0;
-
- retry:
- outdir = Path.Combine (Path.GetTempPath (), "bug79872-" + rnd.Next (10000, 99999));
- if (Directory.Exists (outdir)) {
- try {
- Directory.Delete (outdir, true);
- } catch {
- if (++tries <= 100)
- goto retry;
- }
- }
-
- Directory.CreateDirectory (outdir);
+ string outdir = TempFolder;
AssemblyName an = new AssemblyName ();
an.Name = "bug79872";
// swallow the rest
}
Assert.IsTrue (ok, "Complain on loading a .NET metadata file without an assembly manifest");
-
- Directory.Delete (outdir, true);
}
#endif
Assert.AreEqual (GetType().Assembly, a);
}
-#if NET_4_5
[Test]
public void DefinedTypes_Equality ()
{
Assert.AreSame (x1, x2, "#1");
}
-#endif
class MyAssembly : Assembly { }
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Reflection;
}
}
-#endif
\ No newline at end of file
[TestFixture]
public class ModuleTest
{
- static string TempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.Reflection.ModuleTest");
+ static string BaseTempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.Reflection.ModuleTest");
+ static string TempFolder;
+
+ [TestFixtureSetUp]
+ public void FixtureSetUp ()
+ {
+ try {
+ // Try to cleanup from any previous NUnit run.
+ Directory.Delete (BaseTempFolder, true);
+ } catch (Exception) {
+ }
+ }
[SetUp]
public void SetUp ()
{
- while (Directory.Exists (TempFolder))
- TempFolder = Path.Combine (TempFolder, "2");
+ int i = 0;
+ do {
+ TempFolder = Path.Combine (BaseTempFolder, (++i).ToString());
+ } while (Directory.Exists (TempFolder));
Directory.CreateDirectory (TempFolder);
}
public void TearDown ()
{
try {
- // This throws an exception under MS.NET, since the directory contains loaded
- // assemblies.
+ // This throws an exception under MS.NET and Mono on Windows,
+ // since the directory contains loaded assemblies.
Directory.Delete (TempFolder, true);
} catch (Exception) {
}
Assert.AreEqual (ParamEnum.Foo, info [5].DefaultValue, "#2");
}
-#if NET_4_5
[Test]
public void HasDefaultValueEnum () {
ParameterInfo[] info = typeof (ParameterInfoTest).GetMethod ("paramMethod").GetParameters ();
Assert.IsTrue (info [5].HasDefaultValue);
}
-#endif
public static void Sample2 ([DecimalConstantAttribute(2,2,2,2,2)] decimal a, [DateTimeConstantAttribute(123456)] DateTime b) {}
Assert.AreEqual (pi [1].DefaultValue.GetType (), typeof (Missing), "#2");
}
-#if NET_4_5
[Test]
public void TestHasDefaultValues ()
{
Assert.IsFalse (pi [1].HasDefaultValue, "#2");
Assert.IsTrue (pi [2].HasDefaultValue, "#3");
}
-#endif
public void Sample (int a, [Optional] int b, object c = null)
{
Assert.AreEqual (decimal.MaxValue, info [0].DefaultValue);
}
-#if NET_4_5
[Test]
public void HasDefaultValueDecimal () {
var info = typeof (ParameterInfoTest).GetMethod ("TestC").GetParameters ();
Assert.IsTrue (info [0].HasDefaultValue);
}
-#endif
class TestParamAttribute : Attribute
{
Assert.AreEqual (0, p.GetCustomAttributes (typeof (FlagsAttribute), false).Length, "#3");
Assert.AreEqual (0, p.GetOptionalCustomModifiers ().Length, "#4");
Assert.AreEqual (0, p.GetRequiredCustomModifiers ().Length, "#5");
-#if NET_4_5
try {
var ign = p.HasDefaultValue;
Assert.Fail ("#6");
} catch (NotImplementedException) {
}
-#endif
Assert.IsFalse (p.IsIn, "#7");
#if FEATURE_USE_LCID
Assert.IsFalse (p.IsLcid, "#8");
Assert.IsFalse (p.IsOptional, "#9");
Assert.IsFalse (p.IsOut, "#10");
Assert.IsFalse (p.IsRetval, "#10");
-#if NET_4_5
try {
var ign = p.CustomAttributes;
Assert.Fail ("#11");
} catch (NotImplementedException) {
}
-#endif
try {
p.GetCustomAttributesData ();
Assert.Fail ("#12");
Assert.IsFalse (p2.IsIn, "#1");
p2.MyAttrsImpl = ParameterAttributes.In;
Assert.IsTrue (p2.IsIn, "#2");
-#if NET_4_5
Assert.AreEqual (p2.myList, p2.CustomAttributes, "#3");
-#endif
}
}
}
var p = t.GetProperty ("Prop");
Assert.AreEqual ("test", p.GetConstantValue (), "#1");
- File.Delete (Path.Combine (Path.GetTempPath (), an));
+ try {
+ // This throws an exception under MS.NET and Mono on Windows,
+ // open files cannot be deleted. That's fine.
+ File.Delete (Path.Combine (Path.GetTempPath (), an));
+ } catch (Exception) {
+ }
var pa = typeof (TestE).GetProperty ("PropE");
try {
[TestFixtureSetUp]
public void FixtureSetUp ()
{
- char ds = Path.DirectorySeparatorChar;
- if (ds == '/') {
- string base_path = Path.Combine (Directory.GetCurrentDirectory (), Path.Combine ("Test", "resources"));
- m_ResourceFile = Path.Combine (base_path, "MyResources.resources");
- m_BadResourceFile = Path.Combine (base_path, "Empty.resources");
- } else {
- m_ResourceFile = Path.Combine ("Test", Path.Combine ("resources", "MyResources.resources"));
- m_BadResourceFile = "resources" + ds + "Empty.resources";
- }
+ string base_path = Path.Combine (Directory.GetCurrentDirectory (), Path.Combine ("Test", "resources"));
+ m_ResourceFile = Path.Combine (base_path, "MyResources.resources");
+ m_BadResourceFile = Path.Combine (base_path, "Empty.resources");
}
[SetUp]
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
\ No newline at end of file
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
\ No newline at end of file
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Collections.Generic;
}
}
-#endif
\ No newline at end of file
[Test]
public void GetHINSTANCE ()
{
- if (RunningOnUnix)
- Assert.Ignore ("GetHINSTANCE only applies to Windows.");
+ if (RunningOnMono)
+ Assert.Ignore ("GetHINSTANCE only applies to .NET on Windows.");
Assembly a;
IntPtr hinstance;
}
}
#endif
+
+ [Test]
+ public void GetHRForException ()
+ {
+ Assert.AreEqual (0, Marshal.GetHRForException (null));
+ Assert.IsTrue (Marshal.GetHRForException (new Exception ()) < 0);
+ Assert.AreEqual (12345, Marshal.GetHRForException (new IOException ("test message", 12345)));
+ }
+
[Test] // bug #319009
public void StringToHGlobalUni ()
{
Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr));
Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr, 0));
Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 2));
-#if NET_4_5
Assert.AreEqual (0x4567, Marshal.ReadInt16 ((ptr + 5)));
-#endif
Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 5));
} finally {
Marshal.FreeHGlobal (ptr);
Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr));
Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr, 0));
Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 4));
-#if NET_4_5
Assert.AreEqual (0x77654321, Marshal.ReadInt32 ((ptr + 10)));
-#endif
Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 10));
} finally {
Marshal.FreeHGlobal (ptr);
ex = Marshal.GetExceptionForHR (E_INVALIDARG);
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
}
- bool RunningOnUnix {
+ bool RunningOnMono {
get {
- int p = (int) Environment.OSVersion.Platform;
- return ((p == 4) || (p == 128) || (p == 6));
+ return (Type.GetType ("System.MonoType", false) != null);
}
}
int nSize
);
#endif
+
+ [StructLayout( LayoutKind.Sequential, Pack = 1 )]
+ public class FourByteStruct
+ {
+ public UInt16 value1;
+ public UInt16 value2;
+ }
+
+ [StructLayout( LayoutKind.Sequential, Pack = 1 )]
+ public class ByteArrayFourByteStruct : FourByteStruct
+ {
+ [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
+ public byte[] array;
+ }
+
+ [StructLayout( LayoutKind.Sequential, Pack = 1 )]
+ public class SingleByteStruct
+ {
+ public byte value1;
+ }
+
+ [StructLayout( LayoutKind.Sequential, Pack = 1 )]
+ public class ByteArraySingleByteStruct : SingleByteStruct
+ {
+ [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
+ public byte[] array1;
+ public byte value2;
+ }
+
+ [StructLayout( LayoutKind.Sequential, Pack = 1 )]
+ public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct
+ {
+ [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
+ public byte[] array2;
+ }
+
+ [Test]
+ public void CheckByteArrayFourByteStruct()
+ {
+ ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct
+ { value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) };
+
+ byte[] buffer = Serialize (myStruct);
+
+ UInt16 value1 = BitConverter.ToUInt16 (buffer, 0);
+ UInt16 value2 = BitConverter.ToUInt16 (buffer, 2);
+ string array = Encoding.UTF8.GetString (buffer, 4, 5);
+
+ Assert.AreEqual((UInt16)42, value1);
+ Assert.AreEqual((UInt16)53, value2);
+ Assert.AreEqual ("Hello", array);
+ }
+
+ [Test]
+ public void CheckByteArraySingleByteChildStruct()
+ {
+ ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct
+ { value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53, array2 = Encoding.UTF8.GetBytes( "World" ) };
+
+ byte[] array = Serialize (myStruct);
+
+ byte value1 = array [0];
+ string array1 = Encoding.UTF8.GetString (array, 1, 5);
+ byte value2 = array [6];
+ string array2 = Encoding.UTF8.GetString (array, 7, 5);
+
+ Assert.AreEqual((byte)42, value1);
+ Assert.AreEqual ("Hello", array1);
+ Assert.AreEqual((byte)53, value2);
+ Assert.AreEqual ("World", array2);
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct FiveByteStruct
+ {
+ public uint uIntField;
+ public byte byteField;
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class Base
+ {
+ public ushort firstUShortField;
+ public ushort secondUShortField;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class Derived : Base
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
+ public FiveByteStruct[] arrayField;
+ }
+
+ [Test]
+ public void CheckPtrToStructureWithFixedArrayAndBaseClassFields()
+ {
+ const int arraySize = 6;
+ var derived = new Derived
+ {
+ arrayField = new FiveByteStruct[arraySize],
+ firstUShortField = 42,
+ secondUShortField = 43
+ };
+
+ for (var i = 0; i < arraySize; ++i)
+ {
+ derived.arrayField[i].byteField = (byte)i;
+ derived.arrayField[i].uIntField = (uint)i * 10;
+ }
+
+ var array = Serialize(derived);
+ var deserializedDerived = Deserialize<Derived>(array);
+
+ Assert.AreEqual(derived.firstUShortField, deserializedDerived.firstUShortField, "The firstUShortField differs, which is not expected.");
+ Assert.AreEqual(derived.secondUShortField, deserializedDerived.secondUShortField, "The secondUShortField differs, which is not expected.");
+
+ for (var i = 0; i < arraySize; ++i)
+ {
+ Assert.AreEqual(derived.arrayField[i].byteField, deserializedDerived.arrayField[i].byteField, string.Format("The byteField at index {0} differs, which is not expected.", i));
+ Assert.AreEqual(derived.arrayField[i].uIntField, deserializedDerived.arrayField[i].uIntField, string.Format("The uIntField at index {0} differs, which is not expected.", i));
+ }
+ }
+
+ public static byte[] Serialize( object obj )
+ {
+ int nTypeSize = Marshal.SizeOf( obj );
+ byte[] arrBuffer = new byte[nTypeSize];
+
+ GCHandle hGCHandle = GCHandle.Alloc( arrBuffer, GCHandleType.Pinned );
+ IntPtr pBuffer = hGCHandle.AddrOfPinnedObject();
+ Marshal.StructureToPtr( obj, pBuffer, false );
+ hGCHandle.Free();
+
+ return arrBuffer;
+ }
+
+ public static T Deserialize<T>(byte[] buffer)
+ {
+ var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ var pBuffer = handle.AddrOfPinnedObject();
+ var objResult = (T)Marshal.PtrToStructure(pBuffer, typeof(T));
+ handle.Free();
+
+ return objResult;
+ }
}
#if !MOBILE
[ComImport()]
// ClaimsIdentityTest.cs - NUnit Test Cases for System.Security.Claims.ClaimsIdentity
//
-#if NET_4_5
using NUnit.Framework;
using System;
}
}
-#endif
// ClaimsPrincipalTest.cs - NUnit Test Cases for System.Security.Claims.ClaimsPrincipal
//
-#if NET_4_5
using NUnit.Framework;
using System;
}
}
-#endif
// URL used in SignatureMethod element
CreateFromName ("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "System.Security.Cryptography.DSASignatureDescription");
CreateFromName ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.RSAPKCS1SHA1SignatureDescription");
+ CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.RSAPKCS1SHA256SignatureDescription");
+ CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.RSAPKCS1SHA384SignatureDescription");
+ CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.RSAPKCS1SHA512SignatureDescription");
CreateFromName ("http://www.w3.org/2000/09/xmldsig#hmac-sha1", null);
// URL used in DigestMethod element
CreateFromName ("http://www.w3.org/2000/09/xmldsig#sha1", "System.Security.Cryptography.SHA1CryptoServiceProvider");
MapNameToOID ("System.Security.Cryptography.SHA1", "1.3.14.3.2.26");
// MapNameToOID ("System.Security.Cryptography.HashAlgorithm", "1.3.14.3.2.26");
MapNameToOID ("System.Security.Cryptography.SHA1CryptoServiceProvider", "1.3.14.3.2.26");
+ MapNameToOID ("System.Security.Cryptography.SHA1Cng", "1.3.14.3.2.26");
MapNameToOID ("System.Security.Cryptography.SHA1Managed", "1.3.14.3.2.26");
MapNameToOID ("MD5", "1.2.840.113549.2.5");
MapNameToOID ("System.Security.Cryptography.MD5", "1.2.840.113549.2.5");
MapNameToOID ("System.Security.Cryptography.MD5CryptoServiceProvider", "1.2.840.113549.2.5");
MapNameToOID ("SHA256", "2.16.840.1.101.3.4.2.1");
+ MapNameToOID ("System.Security.Cryptography.SHA256CryptoServiceProvider", "2.16.840.1.101.3.4.2.1");
+ MapNameToOID ("System.Security.Cryptography.SHA256Cng", "2.16.840.1.101.3.4.2.1");
MapNameToOID ("System.Security.Cryptography.SHA256", "2.16.840.1.101.3.4.2.1");
MapNameToOID ("System.Security.Cryptography.SHA256Managed", "2.16.840.1.101.3.4.2.1");
MapNameToOID ("SHA384", "2.16.840.1.101.3.4.2.2");
+ MapNameToOID ("System.Security.Cryptography.SHA384CryptoServiceProvider", "2.16.840.1.101.3.4.2.2");
+ MapNameToOID ("System.Security.Cryptography.SHA384Cng", "2.16.840.1.101.3.4.2.2");
MapNameToOID ("System.Security.Cryptography.SHA384", "2.16.840.1.101.3.4.2.2");
MapNameToOID ("System.Security.Cryptography.SHA384Managed", "2.16.840.1.101.3.4.2.2");
MapNameToOID ("SHA512", "2.16.840.1.101.3.4.2.3");
+ MapNameToOID ("System.Security.Cryptography.SHA512CryptoServiceProvider", "2.16.840.1.101.3.4.2.3");
+ MapNameToOID ("System.Security.Cryptography.SHA512Cng", "2.16.840.1.101.3.4.2.3");
MapNameToOID ("System.Security.Cryptography.SHA512", "2.16.840.1.101.3.4.2.3");
MapNameToOID ("System.Security.Cryptography.SHA512Managed", "2.16.840.1.101.3.4.2.3");
MapNameToOID ("RIPEMD160", "1.3.36.3.2.1");
}
[Test]
- public void RSASignatureDescription ()
+ public void RSASignatureDescription ()
+ {
+// TODO: this would be cleaner with NUnit TestCase'es but they're NUnit 2.5+ :(
+#if FULL_AOT_RUNTIME || MONOTOUCH
+ RSASignatureDescriptionCore ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.SHA1Cng", "System.Security.Cryptography.SHA1CryptoServiceProvider");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.SHA256Cng", "System.Security.Cryptography.SHA256Managed");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.SHA384Cng", "System.Security.Cryptography.SHA384Managed");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.SHA512Cng", "System.Security.Cryptography.SHA512Managed");
+#else
+ RSASignatureDescriptionCore ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.SHA1Cng", "System.Security.Cryptography.SHA1Cng");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.SHA256Cng", "System.Security.Cryptography.SHA256Cng");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.SHA384Cng", "System.Security.Cryptography.SHA384Cng");
+ RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.SHA512Cng", "System.Security.Cryptography.SHA512Cng");
+#endif
+ }
+
+ void RSASignatureDescriptionCore (string name, string expectedDigestAlgorithm, string expectedSelectedDigestAlgorithm)
{
// internal class - we cannot create one without CryptoConfig
- SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName ("http://www.w3.org/2000/09/xmldsig#rsa-sha1");
- Assert.AreEqual ("System.Security.Cryptography.SHA1Cng", sd.DigestAlgorithm);
+ SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName (name);
+ Assert.AreEqual (expectedDigestAlgorithm, sd.DigestAlgorithm);
Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureDeformatter", sd.DeformatterAlgorithm);
Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureFormatter", sd.FormatterAlgorithm);
Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm);
HashAlgorithm hash = sd.CreateDigest();
- Assert.AreEqual ("System.Security.Cryptography.SHA1Cng", hash.ToString ());
+ Assert.AreEqual (expectedSelectedDigestAlgorithm, hash.ToString ());
Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm);
"http://*.go-mono.com",
"http://www.go-mono.com:8080/index.html",
"mono://unknown/protocol",
- Path.DirectorySeparatorChar + "mono" + Path.DirectorySeparatorChar + "index.html",
+ "/mono/index.html",
};
[Test]
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 ()
{
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 ()
--- /dev/null
+//
+// 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 ();
+ }
+ }
+ }
+
+ }
+}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
\ No newline at end of file
Assert.IsTrue (tasks[1].IsCanceled, "#4");
}
-#if NET_4_5
[Test]
public void WaitAll_CancelledAndTimeout ()
{
var t2 = Task.Delay (3000);
Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
}
-#endif
[Test]
public void WaitAllExceptionThenCancelled ()
var token = source.Token;
var evt = new ManualResetEventSlim ();
bool result = false;
- bool thrown = false;
- var task = Task.Factory.StartNew (() => evt.Wait (100));
+ var task = Task.Factory.StartNew (() => { Assert.IsTrue (evt.Wait (2000), "#1"); });
var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
source.Cancel();
evt.Set ();
- task.Wait (100);
+ Assert.IsTrue (task.Wait (2000), "#2");
try {
- cont.Wait (100);
- } catch (Exception ex) {
- thrown = true;
+ Assert.IsFalse (cont.Wait (4000), "#3");
+ } catch (AggregateException ex) {
}
- Assert.IsTrue (task.IsCompleted);
- Assert.IsTrue (cont.IsCanceled);
- Assert.IsFalse (result);
- Assert.IsTrue (thrown);
+ Assert.IsTrue (task.IsCompleted, "#4");
+ Assert.IsTrue (cont.IsCanceled, "#5");
+ Assert.IsFalse (result, "#6");
}
[Test]
}
}
-#if NET_4_5
[Test]
public void ContinuationOnBrokenScheduler ()
{
}
}
-#endif
}
}
[TestFixture]
public class CancellationTokenSourceTest
{
-#if NET_4_5
[Test]
public void Ctor_Invalid ()
Assert.AreEqual (0, called, "#1");
}
-#endif
[Test]
public void Token ()
} catch (ObjectDisposedException) {
}
-#if NET_4_5
try {
cts.CancelAfter (1);
Assert.Fail ("#6");
} catch (ObjectDisposedException) {
}
-#endif
}
[Test]
}
}
-#if NET_4_5
[Test]
public void DisposeRace ()
{
c1.Dispose ();
}
}
-#endif
}
}
{
new EventWaitHandle (true, (EventResetMode) Int32.MinValue);
}
+
+ [Test]
+ public void Disposed_Set ()
+ {
+ var ewh = new EventWaitHandle (false, EventResetMode.ManualReset);
+ ewh.Dispose();
+ try {
+ ewh.Set();
+ Assert.Fail ();
+ } catch (ObjectDisposedException) {
+ }
+ }
}
}
//TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue);
TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1);
- static bool is_win32;
- static bool is_mono;
-
- static ThreadTest ()
- {
- switch (Environment.OSVersion.Platform) {
- case PlatformID.Win32NT:
- case PlatformID.Win32S:
- case PlatformID.Win32Windows:
- case PlatformID.WinCE:
- is_win32 = true;
- break;
- }
-
- // check a class in mscorlib to determine if we're running on Mono
- if (Type.GetType ("Mono.Runtime", false) != null)
- is_mono = true;
- }
-
//Some Classes to test as threads
private class C1Test
{
[Category ("NotDotNet")] // it hangs.
public void TestStart()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on Win32. The test should be fixed.");
{
C1Test test1 = new C1Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
[Test]
public void TestApartmentState ()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on mono on win32. Our runtime should be fixed.");
-
C2Test test1 = new C2Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#1");
[Category ("NotWorking")] // setting the priority of a Thread before it is started isn't implemented in Mono yet
public void TestPriority1()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
C2Test test1 = new C2Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
try {
[Test]
public void TestIsBackground1 ()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
C2Test test1 = new C2Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
try {
[Test]
public void TestName()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
C2Test test1 = new C2Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
try {
[Test]
public void TestThreadState ()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
//TODO: Test The rest of the possible transitions
C2Test test1 = new C2Test();
Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
[Category("NotDotNet")] // On MS, ThreadStateException is thrown on Abort: "Thread is suspended; attempting to abort"
public void TestSuspendAbort ()
{
- if (is_win32 && is_mono)
- Assert.Fail ("This test fails on Win32. The test should be fixed.");
-
Thread t = new Thread (new ThreadStart (DoCount));
t.IsBackground = true;
t.Start ();
}
[Test]
- [Category ("NotDotNet")] // it crashes nunit.
public void Test_InterruptCurrentThread ()
{
ManualResetEvent mre = new ManualResetEvent (false);
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[Test]
+ [Category ("NotDotNet")]
public void CurrentThread_Domains ()
{
AppDomain ad = AppDomain.CreateDomain ("foo");
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
}
}
-#endif
private bool RunningOnWindows {
get {
- int os = (int)Environment.OSVersion.Platform;
- return (os != 4);
+ return Path.DirectorySeparatorChar == '\\';
+ }
+ }
+ private bool RunningOnMono {
+ get {
+ return (Type.GetType ("System.MonoType", false) != null);
}
}
[Test]
public void ApplicationBase1 ()
{
- string expected_path = tmpPath.Replace(@"\", @"/");
+ string expected_path = tmpPath;
AppDomainSetup setup = new AppDomainSetup ();
- string fileUri = "file://" + expected_path;
+ string fileUri = "file://" + tmpPath.Replace(@"\", @"/");
setup.ApplicationBase = fileUri;
- // with MS 1.1 SP1 the expected_path starts with "//" but this make
- // sense only under Windows (i.e. reversed \\ for local files)
- if (RunningOnWindows)
- expected_path = "//" + expected_path;
try {
- // under 2.0 the NotSupportedException is throw when getting
+ // under .NET the NotSupportedException is throw when getting
// (and not setting) the ApplicationBase property
Assert.AreEqual (expected_path, setup.ApplicationBase);
}
catch (NotSupportedException) {
- // however the path is invalid only on Windows
- if (!RunningOnWindows)
+ // however the path is invalid only on .NET
+ if (RunningOnMono)
throw;
}
}
{
AppDomainSetup setup = new AppDomainSetup ();
setup.ApplicationBase = "lala:la";
- try {
- // under 2.0 the NotSupportedException is throw when getting
- // (and not setting) the ApplicationBase property
+ if (!RunningOnWindows) {
Assert.AreEqual (Path.GetFullPath ("lala:la"), setup.ApplicationBase);
- }
- catch (NotSupportedException) {
- // however the path is invalid only on Windows
- // (same exceptions as Path.GetFullPath)
- if (!RunningOnWindows)
- throw;
+ } else {
+ // On Windows we expect a NotSupportedException to be thrown because
+ // of the illegal character (:) in the path
+ try {
+ Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase);
+ }
+ catch (NotSupportedException) {
+ // Expected
+ }
}
}
// This is failing because of (probably) a windows-ism, so don't worry
AppDomainSetup setup = new AppDomainSetup ();
setup.ApplicationBase = "file:///lala:la";
- try {
- // under 2.0 the NotSupportedException is throw when getting
- // (and not setting) the ApplicationBase property
- Assert.AreEqual ("/lala:la", setup.ApplicationBase);
- }
- catch (NotSupportedException) {
- // however the path is invalid only on Windows
- // (same exceptions as Path.GetFullPath)
- if (!RunningOnWindows)
- throw;
+ string expected = "/lala:la";
+ if (!RunningOnWindows) {
+ Assert.AreEqual (expected, setup.ApplicationBase);
+ } else {
+ // On Windows we expect a NotSupportedException to be thrown because
+ // of the illegal character (:) in the path
+ try {
+ Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase);
+ }
+ catch (NotSupportedException) {
+ // Expected
+ }
}
}
setup.ApplicationBase = "la?lala";
// paths containing "?" are *always* bad on Windows
// but are legal for linux so we return a full path
- if (RunningOnWindows) {
+ if (!RunningOnWindows) {
+ Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase);
+ } else {
+ // On Windows we expect a ArgumentException to be thrown because
+ // of the illegal character (?) in the path
try {
- // ArgumentException is throw when getting
- // (and not setting) the ApplicationBase property
- Assert.Fail ("setup.ApplicationBase returned :" + setup.ApplicationBase);
+ Assert.Fail ("ArgumentException expected but setup.ApplicationBase returned:" + setup.ApplicationBase);
}
catch (ArgumentException) {
+ // Expected
+ }
+ }
+ }
+
+ [Test]
+ public void ApplicationBase7 ()
+ {
+ if (RunningOnWindows) {
+ // Extended paths are Windows only
+ AppDomainSetup setup = new AppDomainSetup ();
+ string expected = @"\\?\" + curDir;
+ setup.ApplicationBase = expected;
+ Assert.AreEqual (expected, setup.ApplicationBase);
+ }
+ }
+
+ [Test]
+ public void ApplicationBase8 ()
+ {
+ if (RunningOnWindows) {
+ // Extended paths are Windows only
+ AppDomainSetup setup = new AppDomainSetup ();
+ setup.ApplicationBase = @"\\?\C:\lala:la";
+ try {
+ Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase);
}
- catch (Exception e) {
- Assert.Fail ("Unexpected exception: " + e.ToString ());
+ catch (NotSupportedException) {
+ // Expected
}
- } else {
- Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase);
}
}
Assert.AreEqual (myArrSeg_1 != myArrSeg_2, true);
}
-#if NET_4_5
[Test]
public void IList_NotSupported ()
{
IList<byte> seg = new ArraySegment<byte> (arr);
seg[4] = 3;
}
-#endif
}
}
#if !MOBILE
-#if NET_4_5
[Test]
public void RedirectedTest ()
{
Console.SetError (TextWriter.Null);
Assert.IsFalse (Console.IsErrorRedirected);
}
-#endif
// Bug 678357
[Test]
var del = Delegate.Remove (del1, del2);
}
+ [Test]
+ [ExpectedException (typeof (ArgumentException))]
+ public void CreateDelegateThrowsAnArgumentExceptionWhenCalledWithAnOpenGeneric()
+ {
+ var m = GetType().GetMethod("AnyGenericMethod");
+ Delegate.CreateDelegate(typeof(Action), this, m);
+ }
+
+ public void AnyGenericMethod<T>()
+ {
+ }
+
static bool Int32D2 (int x, int y)
{
return (x & y) == y;
}
[Test]
+ [Culture ("en-US")]
public void Parse ()
{
int i = 0;
Assert.AreEqual (expectedDate, lastMidnightAsEST);
Assert.AreEqual (lastMidnight, lastMidnightAsPST);
}
+
+ [Test]
+ public void ConvertTimeBySystemTimeZoneId_UtcId ()
+ {
+ DateTime localTime = TimeZoneInfo.ConvertTime (DateTime.UtcNow, TimeZoneInfo.Utc, TimeZoneInfo.Local);
+
+ TimeZoneInfo.ConvertTimeBySystemTimeZoneId (DateTime.UtcNow, TimeZoneInfo.Utc.Id, TimeZoneInfo.Local.Id);
+ }
}
[TestFixture]
Assert.IsFalse (Foo.failed);
}
-#if NET_4_5
[Test]
public void WeakReferenceT_TryGetTarget_NullTarget ()
{
object obj;
Assert.IsFalse (r.TryGetTarget (out obj), "#1");
}
-#endif
}
}
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Security;
-
-namespace System.Threading
-{
- //
- // AsyncLocal<T> represents "ambient" data that is local to a given asynchronous control flow, such as an
- // async method. For example, say you want to associate a culture with a given async flow:
- //
- // static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>();
- //
- // static async Task SomeOperationAsync(Culture culture)
- // {
- // s_currentCulture.Value = culture;
- //
- // await FooAsync();
- // }
- //
- // static async Task FooAsync()
- // {
- // PrintStringWithCulture(s_currentCulture.Value);
- // }
- //
- // AsyncLocal<T> also provides optional notifications when the value associated with the current thread
- // changes, either because it was explicitly changed by setting the Value property, or implicitly changed
- // when the thread encountered an "await" or other context transition. For example, we might want our
- // current culture to be communicated to the OS as well:
- //
- // static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>(
- // args =>
- // {
- // NativeMethods.SetThreadCulture(args.CurrentValue.LCID);
- // });
- //
- public sealed class AsyncLocal<T> : IAsyncLocal
- {
- [SecurityCritical] // critical because this action will terminate the process if it throws.
- private readonly Action<AsyncLocalValueChangedArgs<T>> m_valueChangedHandler;
-
- //
- // Constructs an AsyncLocal<T> that does not receive change notifications.
- //
- public AsyncLocal()
- {
- }
-
- //
- // Constructs an AsyncLocal<T> with a delegate that is called whenever the current value changes
- // on any thread.
- //
- [SecurityCritical]
- public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
- {
- m_valueChangedHandler = valueChangedHandler;
- }
-
- public T Value
- {
- [SecuritySafeCritical]
- get
- {
-#if MONO
- throw new NotImplementedException ();
-#else
- object obj = ExecutionContext.GetLocalValue(this);
- return (obj == null) ? default(T) : (T)obj;
-#endif
- }
- [SecuritySafeCritical]
- set
- {
-#if MONO
- throw new NotImplementedException ();
-#else
- ExecutionContext.SetLocalValue(this, value, m_valueChangedHandler != null);
-#endif
- }
- }
-
- [SecurityCritical]
- void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged)
- {
- Contract.Assert(m_valueChangedHandler != null);
- T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj;
- T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj;
- m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
- }
- }
-
- //
- // Interface to allow non-generic code in ExecutionContext to call into the generic AsyncLocal<T> type.
- //
- internal interface IAsyncLocal
- {
- [SecurityCritical]
- void OnValueChanged(object previousValue, object currentValue, bool contextChanged);
- }
-
- public struct AsyncLocalValueChangedArgs<T>
- {
- public T PreviousValue { get; private set; }
- public T CurrentValue { get; private set; }
-
- //
- // If the value changed because we changed to a different ExecutionContext, this is true. If it changed
- // because someone set the Value property, this is false.
- //
- public bool ThreadContextChanged { get; private set; }
-
- internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
- : this()
- {
- PreviousValue = previousValue;
- CurrentValue = currentValue;
- ThreadContextChanged = contextChanged;
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-namespace System.Runtime.CompilerServices
-{
- using System;
-
- [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
- public sealed class DisablePrivateReflectionAttribute : Attribute
- {
- public DisablePrivateReflectionAttribute() {}
- }
-}
-
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-namespace System.Text
-{
- using System;
- using System.Collections;
- using System.Collections.Generic;
-
- [System.Runtime.InteropServices.ComVisible(true)]
- public abstract class EncodingProvider
- {
- public EncodingProvider() { }
- public abstract Encoding GetEncoding(string name);
- public abstract Encoding GetEncoding(int codepage);
-
- // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name
- public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
- {
- Encoding enc = GetEncoding(name);
- if (enc != null)
- {
- enc = (Encoding)GetEncoding(name).Clone();
- enc.EncoderFallback = encoderFallback;
- enc.DecoderFallback = decoderFallback;
- }
-
- return enc;
- }
-
- public virtual Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
- {
- Encoding enc = GetEncoding(codepage);
- if (enc != null)
- {
- enc = (Encoding)GetEncoding(codepage).Clone();
- enc.EncoderFallback = encoderFallback;
- enc.DecoderFallback = decoderFallback;
- }
-
- return enc;
- }
-
- internal static void AddProvider(EncodingProvider provider)
- {
- if (provider == null)
- throw new ArgumentNullException("provider");
-
- lock (s_InternalSyncObject)
- {
- if (s_providers == null)
- {
- s_providers = new EncodingProvider[1] { provider };
- return;
- }
-
- if (Array.IndexOf(s_providers, provider) >= 0)
- {
- return;
- }
-
- var providers = new EncodingProvider[s_providers.Length + 1];
- Array.Copy(s_providers, providers, s_providers.Length);
- providers[providers.Length - 1] = provider;
- s_providers = providers;
- }
- }
-
- internal static Encoding GetEncodingFromProvider(int codepage)
- {
- if (s_providers == null)
- return null;
-
- var providers = s_providers;
- foreach (EncodingProvider provider in providers)
- {
- Encoding enc = provider.GetEncoding(codepage);
- if (enc != null)
- return enc;
- }
-
- return null;
- }
-
- internal static Encoding GetEncodingFromProvider(string encodingName)
- {
- if (s_providers == null)
- return null;
-
- var providers = s_providers;
- foreach (EncodingProvider provider in providers)
- {
- Encoding enc = provider.GetEncoding(encodingName);
- if (enc != null)
- return enc;
- }
-
- return null;
- }
-
- internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec)
- {
- if (s_providers == null)
- return null;
-
- var providers = s_providers;
- foreach (EncodingProvider provider in providers)
- {
- Encoding encing = provider.GetEncoding(codepage, enc, dec);
- if (encing != null)
- return encing;
- }
-
- return null;
- }
-
- internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec)
- {
- if (s_providers == null)
- return null;
-
- var providers = s_providers;
- foreach (EncodingProvider provider in providers)
- {
- Encoding encoding = provider.GetEncoding(encodingName, enc, dec);
- if (encoding != null)
- return encoding;
- }
-
- return null;
- }
-
- private static Object s_InternalSyncObject = new Object();
- private static volatile EncodingProvider[] s_providers;
- }
-}
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-/*============================================================
-**
-** Class: FormattableString
-**
-**
-** Purpose: implementation of the FormattableString
-** class.
-**
-===========================================================*/
-namespace System
-{
- /// <summary>
- /// A composite format string along with the arguments to be formatted. An instance of this
- /// type may result from the use of the C# or VB language primitive "interpolated string".
- /// </summary>
- public abstract class FormattableString : IFormattable
- {
- /// <summary>
- /// The composite format string.
- /// </summary>
- public abstract string Format { get; }
-
- /// <summary>
- /// Returns an object array that contains zero or more objects to format. Clients should not
- /// mutate the contents of the array.
- /// </summary>
- public abstract object[] GetArguments();
-
- /// <summary>
- /// The number of arguments to be formatted.
- /// </summary>
- public abstract int ArgumentCount { get; }
-
- /// <summary>
- /// Returns one argument to be formatted from argument position <paramref name="index"/>.
- /// </summary>
- public abstract object GetArgument(int index);
-
- /// <summary>
- /// Format to a string using the given culture.
- /// </summary>
- public abstract string ToString(IFormatProvider formatProvider);
-
- string IFormattable.ToString(string ignored, IFormatProvider formatProvider)
- {
- return ToString(formatProvider);
- }
-
- /// <summary>
- /// Format the given object in the invariant culture. This static method may be
- /// imported in C# by
- /// <code>
- /// using static System.FormattableString;
- /// </code>.
- /// Within the scope
- /// of that import directive an interpolated string may be formatted in the
- /// invariant culture by writing, for example,
- /// <code>
- /// Invariant($"{{ lat = {latitude}; lon = {longitude} }}")
- /// </code>
- /// </summary>
- public static string Invariant(FormattableString formattable)
- {
- if (formattable == null)
- {
- throw new ArgumentNullException("formattable");
- }
-
- return formattable.ToString(Globalization.CultureInfo.InvariantCulture);
- }
-
- public override string ToString()
- {
- return ToString(Globalization.CultureInfo.CurrentCulture);
- }
- }
-}
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-/*============================================================
-**
-** Class: FormattableStringFactory
-**
-**
-** Purpose: implementation of the FormattableStringFactory
-** class.
-**
-===========================================================*/
-namespace System.Runtime.CompilerServices
-{
- /// <summary>
- /// A factory type used by compilers to create instances of the type <see cref="FormattableString"/>.
- /// </summary>
- public static class FormattableStringFactory
- {
- /// <summary>
- /// Create a <see cref="FormattableString"/> from a composite format string and object
- /// array containing zero or more objects to format.
- /// </summary>
- public static FormattableString Create(string format, params object[] arguments)
- {
- if (format == null)
- {
- throw new ArgumentNullException("format");
- }
-
- if (arguments == null)
- {
- throw new ArgumentNullException("arguments");
- }
-
- return new ConcreteFormattableString(format, arguments);
- }
-
- private sealed class ConcreteFormattableString : FormattableString
- {
- private readonly string _format;
- private readonly object[] _arguments;
-
- internal ConcreteFormattableString(string format, object[] arguments)
- {
- _format = format;
- _arguments = arguments;
- }
-
- public override string Format { get { return _format; } }
- public override object[] GetArguments() { return _arguments; }
- public override int ArgumentCount { get { return _arguments.Length; } }
- public override object GetArgument(int index) { return _arguments[index]; }
- public override string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, _format, _arguments); }
- }
- }
-}
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-//
-
-using Microsoft.Win32.SafeHandles;
-using System.Security;
-
-namespace System.Threading
-{
- public static class WaitHandleExtensions
- {
- /// <summary>
- /// Gets the native operating system handle.
- /// </summary>
- /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
- /// <returns>A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</returns>
- [SecurityCritical]
- public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle)
- {
- if (waitHandle == null)
- {
- throw new ArgumentNullException("waitHandle");
- }
-
- return waitHandle.SafeWaitHandle;
- }
-
- /// <summary>
- /// Sets the native operating system handle
- /// </summary>
- /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
- /// <param name="value">A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</param>
- [SecurityCritical]
- public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle value)
- {
- if (waitHandle == null)
- {
- throw new ArgumentNullException("waitHandle");
- }
-
- waitHandle.SafeWaitHandle = value;
- }
- }
-}
\ No newline at end of file
System.Security.AccessControl/SystemAcl.cs
System.Security.Cryptography/CryptoAPITransform.cs
System.Security.Cryptography/CryptoConfig.cs
-System.Security.Cryptography/CryptoConfig_2_1.cs
+System.Security.Cryptography/CryptoConfig.common.cs
System.Security.Cryptography/CryptoConfig.fullaot.cs
System.Security.Cryptography/CspKeyContainerInfo.cs
System.Security.Cryptography/DESCryptoServiceProvider.cs
System.Text/NormalizationForm.cs
System.Text/Latin1Encoding.cs
System.Threading/CompressedStack.cs
-System.Threading/EventWaitHandle.cs
System.Threading/HostExecutionContext.cs
System.Threading/HostExecutionContextManager.cs
System.Threading/Interlocked.cs
../referencesource/mscorlib/system/fieldaccessexception.cs
../referencesource/mscorlib/system/flagsattribute.cs
../referencesource/mscorlib/system/formatexception.cs
+../referencesource/mscorlib/system/FormattableString.cs
../referencesource/mscorlib/system/guid.cs
../referencesource/mscorlib/system/iappdomain.cs
../referencesource/mscorlib/system/iappdomainsetup.cs
../referencesource/mscorlib/system/runtime/compilerservices/datetimeconstantattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/decimalconstantattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/decoratednameattribute.cs
+../referencesource/mscorlib/system/runtime/compilerservices/disableprivatereflectionattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/discardableattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/extensionattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/fixedaddressvaluetypeattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/fixedbufferattribute.cs
+../referencesource/mscorlib/system/runtime/compilerservices/FormattableStringFactory.cs
../referencesource/mscorlib/system/runtime/compilerservices/hascopysemanticsattribute.cs
../referencesource/mscorlib/system/runtime/compilerservices/IAsyncStateMachine.cs
../referencesource/mscorlib/system/runtime/compilerservices/indexernameattribute.cs
../referencesource/mscorlib/system/text/encoderreplacementfallback.cs
../referencesource/mscorlib/system/text/encoding.cs
../referencesource/mscorlib/system/text/encodinginfo.cs
+../referencesource/mscorlib/system/text/encodingprovider.cs
../referencesource/mscorlib/system/text/mlangcodepageencoding.cs
../referencesource/mscorlib/system/text/surrogateencoder.cs
../referencesource/mscorlib/system/text/unicodeencoding.cs
../referencesource/mscorlib/system/threading/abandonedmutexexception.cs
../referencesource/mscorlib/system/threading/apartmentstate.cs
+../referencesource/mscorlib/system/threading/asynclocal.cs
../referencesource/mscorlib/system/threading/autoresetevent.cs
../referencesource/mscorlib/system/threading/CancellationToken.cs
../referencesource/mscorlib/system/threading/CancellationTokenRegistration.cs
../referencesource/mscorlib/system/threading/CancellationTokenSource.cs
../referencesource/mscorlib/system/threading/CountdownEvent.cs
../referencesource/mscorlib/system/threading/eventresetmode.cs
+../referencesource/mscorlib/system/threading/eventwaithandle.cs
../referencesource/mscorlib/system/threading/executioncontext.cs
../referencesource/mscorlib/system/threading/LazyInitializer.cs
../referencesource/mscorlib/system/threading/lockrecursionexception.cs
../referencesource/mscorlib/system/threading/waithandlecannotbeopenedexception.cs
../referencesource/mscorlib/system/threading/threadpool.cs
../referencesource/mscorlib/system/threading/waithandle.cs
+../referencesource/mscorlib/system/threading/waithandleExtensions.cs
../referencesource/mscorlib/system/threading/Tasks/AsyncCausalityTracer.cs
../referencesource/mscorlib/system/threading/Tasks/BeginEndAwaitableAdapter.cs
ReferenceSources/String.cs
ReferenceSources/Type.cs
-
-coreclr/AsyncLocal.cs
-coreclr/DisablePrivateReflectionAttribute.cs
-coreclr/EncodingProvider.cs
-coreclr/FormattableString.cs
-coreclr/FormattableStringFactory.cs
-coreclr/WaitHandleExtensions.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
-#include corlib.dll.sources
-CommonCrypto/CommonCrypto.cs
-CommonCrypto/CryptorTransform.cs
-CommonCrypto/FastCryptorTransform.cs
-CommonCrypto/CorlibExtras.cs
-CommonCrypto/RijndaelManaged.cs
-CommonCrypto/SecRandom.cs
-CommonCrypto/RC4CommonCrypto.cs
-System/Environment.iOS.cs
-System/Guid.MonoTouch.cs
-System/NotSupportedException.iOS.cs
-CoreFoundation/CFHelpers.cs
-System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
-System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
-System.Text/EncodingHelper.MonoTouch.cs
+#include monotouch_corlib.dll.sources
-#include corlib.dll.sources
-CommonCrypto/CommonCrypto.cs
-CommonCrypto/CryptorTransform.cs
-CommonCrypto/FastCryptorTransform.cs
-CommonCrypto/CorlibExtras.cs
-CommonCrypto/RijndaelManaged.cs
-CommonCrypto/SecRandom.cs
-CommonCrypto/RC4CommonCrypto.cs
-System/Environment.iOS.cs
-System/Guid.MonoTouch.cs
-System/NotSupportedException.iOS.cs
-CoreFoundation/CFHelpers.cs
-System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
-System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
-System.Text/EncodingHelper.MonoTouch.cs
+#include monotouch_corlib.dll.sources
-#include corlib.dll.sources
-CommonCrypto/CommonCrypto.cs
-CommonCrypto/CryptorTransform.cs
-CommonCrypto/FastCryptorTransform.cs
-CommonCrypto/CorlibExtras.cs
-CommonCrypto/RijndaelManaged.cs
-CommonCrypto/SecRandom.cs
-CommonCrypto/RC4CommonCrypto.cs
-System/Environment.iOS.cs
-System/Guid.MonoTouch.cs
-System/NotSupportedException.iOS.cs
-CoreFoundation/CFHelpers.cs
-System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
-System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
-System.Text/EncodingHelper.MonoTouch.cs
+#include monotouch_corlib.dll.sources
-#include corlib.dll.sources
-CommonCrypto/CommonCrypto.cs
-CommonCrypto/CryptorTransform.cs
-CommonCrypto/FastCryptorTransform.cs
-CommonCrypto/CorlibExtras.cs
-CommonCrypto/RijndaelManaged.cs
-CommonCrypto/SecRandom.cs
-CommonCrypto/RC4CommonCrypto.cs
-System/Environment.iOS.cs
-System/Guid.MonoTouch.cs
-System/NotSupportedException.iOS.cs
-CoreFoundation/CFHelpers.cs
-System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
-System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
-System.Text/EncodingHelper.MonoTouch.cs
+#include monotouch_corlib.dll.sources
-#include corlib.dll.sources
-CommonCrypto/CommonCrypto.cs
-CommonCrypto/CryptorTransform.cs
-CommonCrypto/FastCryptorTransform.cs
-CommonCrypto/CorlibExtras.cs
-CommonCrypto/RijndaelManaged.cs
-CommonCrypto/SecRandom.cs
-CommonCrypto/RC4CommonCrypto.cs
-System/Environment.iOS.cs
-System/Guid.MonoTouch.cs
-System/NotSupportedException.iOS.cs
-CoreFoundation/CFHelpers.cs
-System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
-System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
-System.Text/EncodingHelper.MonoTouch.cs
+#include monotouch_corlib.dll.sources
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,
),
binder.ReturnType
);
+#endif
resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
}
lockID = Interlocked.Increment(ref s_nextLockID);
}
-#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
-#endif
private static bool IsRWEntryEmpty(ReaderWriterCount rwc)
{
if (rwc.lockID == 0)
/// entry for this thread, but doesn't want to add one if an existing one
/// could not be found.
/// </summary>
-#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
-#endif
private ReaderWriterCount GetThreadRWCount(bool dontAllocate)
{
ReaderWriterCount rwc = t_rwc;
return owners & READER_MASK;
}
-#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
-#endif
private void EnterMyLock()
{
if (Interlocked.CompareExchange(ref myLock, 1, 0) != 0)
}
#endif
+#if !MONO
#if FEATURE_NETCORE
[SecuritySafeCritical]
#endif
int errorCode = Marshal.GetLastWin32Error();
WinIOError(errorCode, str);
}
+#endif
// After calling GetLastWin32Error(), it clears the last error field,
// so you must save the HResult and pass it to this method. This method
if(null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle,name));
+#if MONO
+ InternalResources.WinIOError(errorCode, "");
+#else
InternalResources.WinIOError();
+#endif
}
this.SafeWaitHandle = myHandle;
}
{
if(null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle,name));
+
+#if MONO
+ InternalResources.WinIOError(errorCode, "");
+#else
InternalResources.WinIOError();
+#endif
}
createdNew = errorCode != NativeMethods.ERROR_ALREADY_EXISTS;
this.SafeWaitHandle = myHandle;
if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
return OpenExistingResult.NameInvalid;
//this is for passed through NativeMethods Errors
+#if MONO
+ InternalResources.WinIOError(errorCode, "");
+#else
InternalResources.WinIOError();
+#endif
}
result = new Semaphore(myHandle);
return OpenExistingResult.Success;
#endif
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)]
[System.Runtime.InteropServices.ComVisible(true)]
-#if !MONOTOUCH
- public
-#endif
- sealed class ComImportAttribute : Attribute
+ public sealed class ComImportAttribute : Attribute
{
internal static Attribute GetCustomAttribute(RuntimeType type)
{
**
**
=============================================================================*/
-#if !FULL_AOT_RUNTIME
+
namespace System.Runtime.InteropServices {
using System;
{
if (obj != null)
{
+#if FULL_AOT_RUNTIME
+ throw new PlatformNotSupportedException ();
+#else
// Make sure this guy has an IDispatch
IntPtr pdisp = Marshal.GetIDispatchForObject(obj);
// If we got here without throwing an exception, the QI for IDispatch succeeded.
Marshal.Release(pdisp);
+#endif
}
m_WrappedObject = obj;
}
private Object m_WrappedObject;
}
}
-#endif
\ No newline at end of file
**
**
=============================================================================*/
-#if !FULL_AOT_RUNTIME
+
namespace System.Runtime.InteropServices {
using System;
private int m_ErrorCode;
}
}
-#endif
\ No newline at end of file
=============================================================================*/
+#if !MOBILE
#if !FEATURE_MACL
namespace System.Security.AccessControl
{
}
}
#endif
+#endif
namespace System.Threading
{
Contract.EndContractBlock();
SafeWaitHandle _handle = null;
+#if MONO
+ int errorCode;
+#endif
switch(mode)
{
case EventResetMode.ManualReset:
+#if MONO
+ _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (true, initialState, name, out errorCode), true);
+#else
_handle = Win32Native.CreateEvent(null, true, initialState, name);
+#endif
break;
case EventResetMode.AutoReset:
+#if MONO
+ _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (false, initialState, name, out errorCode), true);
+#else
_handle = Win32Native.CreateEvent(null, false, initialState, name);
+#endif
break;
default:
if (_handle.IsInvalid)
{
+#if !MONO
int errorCode = Marshal.GetLastWin32Error();
+#endif
_handle.SetHandleAsInvalid();
if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
}
Contract.EndContractBlock();
Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if !MONO
#if FEATURE_MACL
// For ACL's, get the security descriptor from the EventWaitHandleSecurity.
if (eventSecurity != null) {
Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length);
secAttrs.pSecurityDescriptor = pSecDescriptor;
}
+#endif
#endif
SafeWaitHandle _handle = null;
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag",name));
};
+#if MONO
+ int errorCode;
+ _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (isManualReset, initialState, name, out errorCode), true);
+#else
_handle = Win32Native.CreateEvent(secAttrs, isManualReset, initialState, name);
int errorCode = Marshal.GetLastWin32Error();
+#endif
if (_handle.IsInvalid)
{
result = null;
+#if MOBILE
+ throw new NotSupportedException ();
+#else
+
+#if MONO
+ int errorCode;
+ var myHandle = new SafeWaitHandle (NativeEventCalls.OpenEvent_internal (name, rights, out errorCode), true);
+#else
#if FEATURE_MACL
SafeWaitHandle myHandle = Win32Native.OpenEvent((int) rights, false, name);
#else
SafeWaitHandle myHandle = Win32Native.OpenEvent(Win32Native.EVENT_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);
+#endif
#endif
if (myHandle.IsInvalid)
{
+#if !MONO
int errorCode = Marshal.GetLastWin32Error();
+#endif
if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode)
return OpenExistingResult.NameNotFound;
}
result = new EventWaitHandle(myHandle);
return OpenExistingResult.Success;
+#endif
}
[System.Security.SecuritySafeCritical] // auto-generated
public bool Reset()
{
+#if MONO
+ var res = NativeEventCalls.ResetEvent(safeWaitHandle);
+#else
bool res = Win32Native.ResetEvent(safeWaitHandle);
+#endif
if (!res)
+#if MONO
+ throw new IOException ();
+#else
__Error.WinIOError();
+#endif
return res;
}
[System.Security.SecuritySafeCritical] // auto-generated
public bool Set()
{
+#if MONO
+ var res = NativeEventCalls.SetEvent(safeWaitHandle);
+#else
bool res = Win32Native.SetEvent(safeWaitHandle);
+#endif
if (!res)
+#if MONO
+ throw new IOException ();
+#else
__Error.WinIOError();
+#endif
return res;
}
-#if FEATURE_MACL
+#if FEATURE_MACL || MOBILE
[System.Security.SecuritySafeCritical] // auto-generated
public EventWaitHandleSecurity GetAccessControl()
{
return new EventWaitHandleSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
}
+#endif
+#if FEATURE_MACL
[System.Security.SecuritySafeCritical] // auto-generated
public void SetAccessControl(EventWaitHandleSecurity eventSecurity)
{
dls.Store.SetData(slot, data);
}
-#if !MONO
// #threadCultureInfo
//
}
#if! FEATURE_LEAK_CULTURE_INFO
+
+#if MONO
+ static void nativeInitCultureAccessors()
+ {
+ m_CurrentCulture = CultureInfo.ConstructCurrentCulture ();
+ m_CurrentUICulture = CultureInfo.ConstructCurrentUICulture ();
+ }
+#else
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private static extern void nativeInitCultureAccessors();
#endif
+#endif
+
+#if !MONO
/*=============================================================*/
--- /dev/null
+// CS0246: The type or namespace name `Foo' could not be found. Are you missing an assembly reference?
+// Line: 8
+
+class Crashy
+{
+ void Call (System.Action<object> action) { }
+
+ public void DoCrash () => Call (f => f as Foo);
+}
ls -l mcs2.exe mcs3.exe
mcs2.exe: $(PROGRAM)
- $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response)
+ $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) $(MCS_REFERENCES) -target:exe -out:$@ $(BUILT_SOURCES) $(EXTRA_SOURCES) @$(response)
mcs3.exe: mcs2.exe
- $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response)
+ $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) $(MCS_REFERENCES) -target:exe -out:$@ $(BUILT_SOURCES) $(EXTRA_SOURCES) @$(response)
wc:
wc -l $(BUILT_SOURCES) `cat $(sourcefile)`
if (res && errors != ec.Report.Errors)
return null;
+ if (block.IsAsync && block.Original.ParametersBlock.HasCapturedThis && ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.block.IsAsync) {
+ //
+ // We'll do ldftn to load the fabricated m_X method but
+ // because we are inside struct the method can be hoisted
+ // anywhere in the parent scope
+ //
+ ec.CurrentBlock.ParametersBlock.HasReferenceToStoreyForInstanceLambdas = true;
+ }
+
return res ? this : null;
}
parent = storey = sm;
}
}
+ } else if (src_block.ParametersBlock.HasReferenceToStoreyForInstanceLambdas) {
+ src_block.ParametersBlock.StateMachine.AddParentStoreyReference (ec, storey);
}
modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
bool IsFriendAssemblyTo (IAssemblyDefinition assembly);
}
- public class AssemblyReferenceErrorInfo
+ public class AssemblyReferenceMessageInfo
{
- public AssemblyReferenceErrorInfo (AssemblyName dependencyName, string location, string message)
+ public AssemblyReferenceMessageInfo (AssemblyName dependencyName, Action<Report> reportMessage)
{
this.DependencyName = dependencyName;
- this.RequestingAssemblyLocation = location;
- this.Message = message;
+ this.ReportMessage = reportMessage;
}
public AssemblyName DependencyName { get; private set; }
- public string RequestingAssemblyLocation { get; private set; }
- public string Message { get; private set; }
+ public Action<Report> ReportMessage { get; private set; }
}
public abstract class AssemblyDefinition : IAssemblyDefinition
// due to type-forwarding
//
if (references.Any (l => l.Name == r.DependencyName.Name)) {
- Report.SymbolRelatedToPreviousError (r.RequestingAssemblyLocation);
- Report.Error (1705, r.Message);
+ r.ReportMessage (Report);
}
}
}
return public_key_token;
}
- protected virtual List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
+ protected virtual List<AssemblyReferenceMessageInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
{
return null;
}
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;
}
while (c == ' ' || c == '\t')
c = get_char ();
- if (c == '\n' || c == UnicodeLS || c == UnicodePS)
- advance_line ();
-
return number;
}
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (type == null) {
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) {
if (TypeManager.IsGenericParameter (type)) {
ec.Report.Error (413, loc,
return Builder.__AddModule (moduleFile);
}
- protected override List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
+ protected override List<AssemblyReferenceMessageInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
{
return loader.GetNotUnifiedReferences (assemblyName);
}
Assembly corlib;
readonly List<Tuple<AssemblyName, string, Assembly>> loaded_names;
static readonly Dictionary<string, string[]> sdk_directory;
- Dictionary<AssemblyName, List<AssemblyReferenceErrorInfo>> resolved_version_mismatches;
+ Dictionary<AssemblyName, List<AssemblyReferenceMessageInfo>> resolved_version_mismatches;
static readonly TypeName objectTypeName = new TypeName ("System", "Object");
static StaticLoader ()
var v2 = version_mismatch.GetName ().Version;
if (v1 > v2) {
- if (resolved_version_mismatches == null)
- resolved_version_mismatches = new Dictionary<AssemblyName, List<AssemblyReferenceErrorInfo>> ();
-
- var an = args.RequestingAssembly.GetName ();
- List<AssemblyReferenceErrorInfo> names;
- if (!resolved_version_mismatches.TryGetValue (an, out names)) {
- names = new List<AssemblyReferenceErrorInfo> ();
- resolved_version_mismatches.Add (an, names);
- }
-
- names.Add (new AssemblyReferenceErrorInfo (ref_an, args.RequestingAssembly.Location,
- string.Format ("Assembly `{0}' depends on `{1}' which has a higher version number than referenced assembly `{2}'",
- args.RequestingAssembly.FullName, refname, version_mismatch.GetName ().FullName)));
+ var messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => {
+ report.SymbolRelatedToPreviousError (args.RequestingAssembly.Location);
+ report.Error (1705, string.Format ("Assembly `{0}' depends on `{1}' which has a higher version number than referenced assembly `{2}'",
+ args.RequestingAssembly.FullName, refname, version_mismatch.GetName ().FullName));
+ });
+ AddReferenceVersionMismatch (args.RequestingAssembly.GetName (), messageInfo);
return version_mismatch;
}
if (!is_fx_assembly) {
- if (v1.Major != v2.Major || v1.Minor != v2.Minor) {
- compiler.Report.Warning (1701, 2,
- "Assuming assembly reference `{0}' matches assembly `{1}'. You may need to supply runtime policy",
- refname, version_mismatch.GetName ().FullName);
- } else {
- compiler.Report.Warning (1702, 3,
- "Assuming assembly reference `{0}' matches assembly `{1}'. You may need to supply runtime policy",
- refname, version_mismatch.GetName ().FullName);
- }
+ var messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => {
+ if (v1.Major != v2.Major || v1.Minor != v2.Minor) {
+ report.Warning (1701, 2,
+ "Assuming assembly reference `{0}' matches assembly `{1}'. You may need to supply runtime policy",
+ refname, version_mismatch.GetName ().FullName);
+ } else {
+ report.Warning (1702, 3,
+ "Assuming assembly reference `{0}' matches assembly `{1}'. You may need to supply runtime policy",
+ refname, version_mismatch.GetName ().FullName);
+ }
+ });
+
+ AddReferenceVersionMismatch (args.RequestingAssembly.GetName (), messageInfo);
}
return version_mismatch;
return domain.CreateMissingAssembly (args.Name);
}
+ void AddReferenceVersionMismatch (AssemblyName an, AssemblyReferenceMessageInfo errorInfo)
+ {
+ if (resolved_version_mismatches == null)
+ resolved_version_mismatches = new Dictionary<AssemblyName, List<AssemblyReferenceMessageInfo>> ();
+
+ List<AssemblyReferenceMessageInfo> names;
+ if (!resolved_version_mismatches.TryGetValue (an, out names)) {
+ names = new List<AssemblyReferenceMessageInfo> ();
+ resolved_version_mismatches.Add (an, names);
+ }
+
+ names.Add (errorInfo);
+ }
+
public void Dispose ()
{
domain.Dispose ();
return default_references.ToArray ();
}
- public List<AssemblyReferenceErrorInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
+ public List<AssemblyReferenceMessageInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
{
- List<AssemblyReferenceErrorInfo> list = null;
+ List<AssemblyReferenceMessageInfo> list = null;
if (resolved_version_mismatches != null)
resolved_version_mismatches.TryGetValue (assemblyName, out list);
AwaitBlock = 1 << 13,
FinallyBlock = 1 << 14,
CatchBlock = 1 << 15,
+ HasReferenceToStoreyForInstanceLambdas = 1 << 16,
Iterator = 1 << 20,
NoFlowAnalysis = 1 << 21,
InitializationEmitted = 1 << 22
break;
}
}
-
+
//
// We are the first storey on path and 'this' has to be hoisted
//
//
// If we are state machine with no parent. We can hook into parent without additional
- // reference and capture this directly
+ // reference and capture this directly
//
ExplicitBlock parent_storey_block = pb;
while (parent_storey_block.Parent != null) {
#region Properties
+ public bool HasReferenceToStoreyForInstanceLambdas {
+ get {
+ return (flags & Flags.HasReferenceToStoreyForInstanceLambdas) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.HasReferenceToStoreyForInstanceLambdas : flags & ~Flags.HasReferenceToStoreyForInstanceLambdas;
+ }
+ }
+
public bool IsAsync {
get {
return (flags & Flags.HasAsyncModifier) != 0;
ec.EmitInt (first_resume_pc);
ec.Emit (OpCodes.Sub);
- var labels = new Label[resume_points.Count - System.Math.Max (first_catch_resume_pc, 0)];
+ var labels = new Label [first_catch_resume_pc > 0 ? first_catch_resume_pc : resume_points.Count];
for (int i = 0; i < labels.Length; ++i)
labels[i] = resume_points[i].PrepareForEmit (ec);
ec.Emit (OpCodes.Switch, labels);
--- /dev/null
+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
--- /dev/null
+using System;
+using System.Threading.Tasks;
+
+public class Test
+{
+ static async Task<string> AsyncWithDeepTry ()
+ {
+ try {
+ await Task.Yield ();
+
+ try {
+ await Task.Yield ();
+ } catch {
+ }
+ } catch {
+ await Task.Yield ();
+ } finally {
+ }
+
+ return null;
+ }
+
+
+ static void Main ()
+ {
+ AsyncWithDeepTry ().Wait ();
+ }
+}
--- /dev/null
+using System;
+using System.Threading.Tasks;
+
+class X
+{
+ public static void Main ()
+ {
+ new X ().Test ();
+ }
+
+ void Test ()
+ {
+ object v1 = null;
+
+ Action a = () =>
+ {
+ if (v1 == null)
+ {
+ object v2 = null;
+
+ Action a2 = () =>
+ {
+ Console.WriteLine (v2);
+ };
+
+ Action a3 = async () =>
+ {
+ // This scope needs to access to Scope which can do ldftn on instance method
+ {
+ Func<Task> a4 = async () =>
+ {
+ await Foo ();
+ };
+ }
+
+ await Task.Yield ();
+ };
+
+ a3 ();
+ }
+ };
+
+ a ();
+ }
+
+ async Task Foo ()
+ {
+ await Task.FromResult (1);
+ }
+
+}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
- <file id="1" name="test-debug-30.cs" checksum="d3addfa69f16faf00991ef839451a975" />
+ <file id="1" name="test-debug-30.cs" checksum="5303b32b0208123737567d53022ae3d5" />
</files>
<methods>
<method token="0x6000001">
<locals />
<scopes />
</method>
+ <method token="0x6000004">
+ <sequencepoints>
+ <entry il="0x0" row="23" col="2" file_ref="1" hidden="false" />
+ <entry il="0x1" row="24" col="3" file_ref="1" hidden="false" />
+ <entry il="0x6" row="25" col="2" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes />
+ </method>
</methods>
</symbols>
\ No newline at end of file
{
return;
}
+
+#pragma warning disable 618
+#pragma warning restore 618
+
+ void OneMore ()
+ {
+ return;
+ }
}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="dtest-065.cs">
+ <type name="TestConvert">
+ <method name="Boolean TryConvert(System.Dynamic.ConvertBinder, System.Object ByRef)" attrs="198">
+ <size>13</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="Test">
+ <method name="Boolean TryInvokeMember(System.Dynamic.InvokeMemberBinder, System.Object[], System.Object ByRef)" attrs="198">
+ <size>17</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="XX">
+ <method name="Void Main()" attrs="150">
+ <size>154</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="dtest-anontype-01.cs">
<type name="C">
<method name="Void Main()" attrs="150">
</method>
</type>
</test>
+ <test name="test-async-88.cs">
+ <type name="Test">
+ <method name="System.Threading.Tasks.Task`1[System.String] AsyncWithDeepTry()" attrs="145">
+ <size>33</size>
+ </method>
+ <method name="Void Main()" attrs="145">
+ <size>12</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="Test+<AsyncWithDeepTry>c__async0">
+ <method name="Void MoveNext()" attrs="486">
+ <size>460</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-async-89.cs">
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>12</size>
+ </method>
+ <method name="Void Test()" attrs="129">
+ <size>41</size>
+ </method>
+ <method name="System.Threading.Tasks.Task Foo()" attrs="129">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1">
+ <method name="Void <>m__0()" attrs="131">
+ <size>67</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Foo>c__async0">
+ <method name="Void MoveNext()" attrs="486">
+ <size>158</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2">
+ <method name="Void <>m__0()" attrs="131">
+ <size>13</size>
+ </method>
+ <method name="Void <>m__1()" attrs="131">
+ <size>48</size>
+ </method>
+ <method name="System.Threading.Tasks.Task <>m__2()" attrs="131">
+ <size>46</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2+<Test>c__async3">
+ <method name="Void MoveNext()" attrs="486">
+ <size>179</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2+<Test>c__async4">
+ <method name="Void MoveNext()" attrs="486">
+ <size>167</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ </test>
<test name="test-cls-00.cs">
<type name="CLSCLass_6">
<method name="Void add_Disposed(Delegate)" attrs="2182">
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
+ <method name="Void OneMore()" attrs="129">
+ <size>7</size>
+ </method>
</type>
</test>
<test name="test-decl-expr-01.cs">
using System.IO;
using System.Collections;
using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
using System.Security.Cryptography;
using System.Text;
using System.Configuration.Assemblies;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
using Mono.Security.Cryptography;
-using IKR = IKVM.Reflection;
namespace Mono.AssemblyLinker
{
No
}
+ public enum Platform {
+ AnyCPU,
+ AnyCPU32Preferred,
+ Arm,
+ X86,
+ X64,
+ IA64
+ }
+
public class AssemblyLinker {
ArrayList inputFiles = new ArrayList ();
string entryPoint;
string win32IconFile;
string win32ResFile;
+ string title;
+ string description;
+ string company;
+ string product;
+ string copyright;
+ string trademark;
string templateFile;
bool isTemplateFile = false;
Target target = Target.Dll;
+ Platform platform = Platform.AnyCPU;
DelaySign delaysign = DelaySign.NotSet;
string keyfile;
string keyname;
string culture;
+ Universe universe;
public static int Main (String[] args) {
return new AssemblyLinker ().DynMain (args);
}
private int DynMain (String[] args) {
- ParseArgs (args);
+ using (universe = new Universe (UniverseOptions.MetadataOnly)) {
+ universe.LoadFile (typeof (object).Assembly.Location);
+ ParseArgs (args);
- DoIt ();
+ DoIt ();
- return 0;
+ return 0;
+ }
}
private void ParseArgs (string[] args)
if (realArg.StartsWith ("0x"))
realArg = realArg.Substring (2);
uint val = Convert.ToUInt32 (realArg, 16);
- AddCattr (typeof (AssemblyAlgorithmIdAttribute), typeof (uint), val);
+ AddCattr (typeof (System.Reflection.AssemblyAlgorithmIdAttribute), typeof (uint), val);
} catch (Exception) {
ReportInvalidArgument (opt, arg);
}
case "company":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyCompanyAttribute), arg);
+ company = arg;
return true;
case "config":
case "configuration":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyConfigurationAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyConfigurationAttribute), arg);
return true;
case "copy":
case "copyright":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyCopyrightAttribute), arg);
+ copyright = arg;
return true;
case "c":
case "description":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyDescriptionAttribute), arg);
+ description = arg;
return true;
case "e":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyFileVersionAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyFileVersionAttribute), arg);
return true;
case "flags":
if (realArg.StartsWith ("0x"))
realArg = realArg.Substring (2);
uint val = Convert.ToUInt32 (realArg, 16);
- AddCattr (typeof (AssemblyFlagsAttribute), typeof (uint), val);
+ AddCattr (typeof (System.Reflection.AssemblyFlagsAttribute), typeof (uint), val);
} catch (Exception) {
ReportInvalidArgument (opt, arg);
}
outFile = arg;
return true;
+ case "platform":
+ if (arg == null)
+ ReportMissingText (opt);
+ switch (arg.ToLowerInvariant ()) {
+ case "arm":
+ platform = Platform.Arm;
+ break;
+ case "anycpu":
+ platform = Platform.AnyCPU;
+ break;
+ case "x86":
+ platform = Platform.X86;
+ break;
+ case "x64":
+ platform = Platform.X64;
+ break;
+ case "itanium":
+ platform = Platform.IA64;
+ break;
+ case "anycpu32bitpreferred":
+ platform = Platform.AnyCPU32Preferred;
+ break;
+ default:
+ ReportInvalidArgument (opt, arg);
+ break;
+ }
+ return true;
+
case "prod":
case "product":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyProductAttribute), arg);
+ product = arg;
return true;
case "productv":
case "productversion":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyInformationalVersionAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyInformationalVersionAttribute), arg);
return true;
case "t":
case "title":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyTitleAttribute), arg);
+ title = arg;
return true;
case "trade":
case "trademark":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyTrademarkAttribute), arg);
+ trademark = arg;
return true;
case "v":
Version ();
break;
}
- AddCattr (typeof (AssemblyVersionAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyVersionAttribute), arg);
return true;
case "win32icon":
return command.ToLower ();
}
- private void AddCattr (Type attrType, Type arg, object value) {
- cattrs.Add (new CustomAttributeBuilder (attrType.GetConstructor (new Type [] { arg }), new object [] { value }));
+ private void AddCattr (System.Type attrType, System.Type arg, object value) {
+ var importedAttrType = universe.Import(attrType);
+ var importedArg = universe.Import(arg);
+
+ cattrs.Add (new CustomAttributeBuilder (importedAttrType.GetConstructor (new [] { importedArg }), new [] { value }));
}
- private void AddCattr (Type attrType, object value) {
+ private void AddCattr (System.Type attrType, object value) {
AddCattr (attrType, typeof (string), value);
}
if (isTemplateFile)
aname = ReadCustomAttributesFromTemplateFile (templateFile, aname);
+ if (!String.IsNullOrEmpty (title))
+ AddCattr (typeof (System.Reflection.AssemblyTitleAttribute), title);
+ if (!String.IsNullOrEmpty (description))
+ AddCattr (typeof (System.Reflection.AssemblyDescriptionAttribute), description);
+ if (!String.IsNullOrEmpty (company))
+ AddCattr (typeof (System.Reflection.AssemblyCompanyAttribute), company);
+ if (!String.IsNullOrEmpty (product))
+ AddCattr (typeof (System.Reflection.AssemblyProductAttribute), product);
+ if (!String.IsNullOrEmpty (copyright))
+ AddCattr (typeof (System.Reflection.AssemblyCopyrightAttribute), copyright);
+ if (!String.IsNullOrEmpty (trademark))
+ AddCattr (typeof (System.Reflection.AssemblyTrademarkAttribute), trademark);
+
SetKeyPair (aname);
if (fileName != outFile)
- ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile));
+ ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile));
else
- ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save);
+ ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save);
foreach (CustomAttributeBuilder cb in cattrs)
ab.SetCustomAttribute (cb);
*/
foreach (ModuleInfo mod in inputFiles) {
- MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
- if (mi == null)
- Report (0, "Cannot add modules on this runtime: try the Mono runtime instead.");
-
if (mod.target != null) {
File.Copy (mod.fileName, mod.target, true);
mod.fileName = mod.target;
if (isAssembly)
ReportWarning (1020, "Ignoring included assembly '" + mod.fileName + "'");
else
- mi.Invoke (ab, new object [] { mod.fileName });
+ ab.__AddModule (universe.OpenRawModule(mod.fileName));
}
/*
MethodInfo mainMethodInfo = null;
try {
- Type mainType = ab.GetType (mainClass);
+ IKVM.Reflection.Type mainType = ab.GetType (mainClass);
if (mainType != null)
mainMethodInfo = mainType.GetMethod (mainMethod);
}
if (win32IconFile != null) {
try {
- MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
- if (mi == null)
- Report (0, "Cannot embed win32 icons on this runtime: try the Mono runtime instead.");
- mi.Invoke (ab, new object [] { win32IconFile });
+ ab.__DefineIconResource (File.ReadAllBytes (win32IconFile));
}
catch (Exception ex) {
Report (1031, "Error reading icon '" + win32IconFile + "' --" + ex);
}
}
+ ModuleBuilder mainModule = null;
+
foreach (ResourceInfo res in resources) {
if (res.name == null)
res.name = Path.GetFileName (res.fileName);
Report (1046, String.Format ("Resource identifier '{0}' has already been used in this assembly", res.name));
if (res.isEmbedded) {
- MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
- null, CallingConventions.Any, new Type [] { typeof (string), typeof (string) }, null);
- if (mi == null)
- Report (0, "Cannot embed resources on this runtime: try the Mono runtime instead.");
- mi.Invoke (ab, new object [] { res.name, res.fileName });
+ if (mainModule == null) {
+ mainModule = ab.DefineDynamicModule (fileName, fileName, false);
+ }
+
+ Stream stream = new MemoryStream (File.ReadAllBytes (res.fileName));
+
+ mainModule.DefineManifestResource (res.name, stream, res.isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public);
}
else {
if (res.target != null) {
}
}
+ PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly;
+ ImageFileMachine machine;
+
+ switch (platform) {
+ case Platform.X86:
+ pekind |= PortableExecutableKinds.Required32Bit;
+ machine = ImageFileMachine.I386;
+ break;
+ case Platform.X64:
+ pekind |= PortableExecutableKinds.PE32Plus;
+ machine = ImageFileMachine.AMD64;
+ break;
+ case Platform.IA64:
+ machine = ImageFileMachine.IA64;
+ break;
+ case Platform.AnyCPU32Preferred:
+ pekind |= PortableExecutableKinds.Preferred32Bit;
+ machine = ImageFileMachine.I386;
+ break;
+ case Platform.Arm:
+ machine = ImageFileMachine.ARM;
+ break;
+ case Platform.AnyCPU:
+ default:
+ machine = ImageFileMachine.I386;
+ break;
+ }
+
try {
- ab.Save (fileName);
+ ab.Save (fileName, pekind, machine);
}
catch (Exception ex) {
Report (1019, "Metadata failure creating assembly -- " + ex);
{
// LAMESPEC: according to MSDN, the template assembly must have a
// strong name but this is not enforced
- const IKR.UniverseOptions options = IKR.UniverseOptions.MetadataOnly;
-
- var universe = new IKR.Universe (options);
var asm = universe.LoadFile (templateFile);
// Create missing assemblies, we don't want to load them!
// Code taken from ikdasm
var names = new HashSet<string> ();
- IKR.AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies ();
+ AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies ();
- var resolved_assemblies = new IKR.Assembly [assembly_refs.Length];
+ var resolved_assemblies = new Assembly [assembly_refs.Length];
for (int i = 0; i < resolved_assemblies.Length; i++) {
string name = assembly_refs [i].Name;
keyname = key_name_value;
}
break;
+
+ case "System.Reflection.AssemblyTitleAttribute": {
+ if (title != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyTitleAttribute .ctor(string title)
+ string title_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (title_value))
+ title = title_value;
+ }
+ break;
+
+ case "System.Reflection.AssemblyDescriptionAttribute": {
+ if (description != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyDescriptionAttribute .ctor(string description)
+ string description_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (description_value))
+ description = description_value;
+ }
+ break;
+
+ case "System.Reflection.AssemblyProductAttribute": {
+ if (product != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyProductAttribute .ctor(string product)
+ string product_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (product_value))
+ product = product_value;
+ }
+ break;
+
+ case "System.Reflection.AssemblyCompanyAttribute": {
+ if (company != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyCompanyAttribute .ctor(string company)
+ string company_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (company_value))
+ company = company_value;
+
+ }
+ break;
+
+ case "System.Reflection.AssemblyCopyrightAttribute": {
+ if (copyright != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyCopyrightAttribute .ctor(string copyright)
+ string copyright_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (copyright_value))
+ copyright = copyright_value;
+ }
+ break;
+
+ case "System.Reflection.AssemblyTrademarkAttribute": {
+ if (trademark != null)
+ // ignore if specified on command line
+ continue;
+
+ // AssemblyTrademarkAttribute .ctor(string trademark)
+ string trademark_value = (string) attr_data.ConstructorArguments [0].Value;
+
+ if (!String.IsNullOrEmpty (trademark_value))
+ trademark = trademark_value;
+ }
+ break;
}
}
" /main:<method> Specifies the method name of the entry point",
" /nologo Suppress the startup banner and copyright message",
" /out:<filename> Output file name for the assembly manifest",
+ " /platform:<text> Limit which platforms this code can run on; must be",
+ " one of x86, Itanium, x64, arm, anycpu32bitpreferred,",
+ " or anycpu (the default)",
" /prod[uct]:<text> Product name",
" /productv[ersion]:<text> Product version",
" /t[arget]:lib[rary] Create a library",
if (!(memberDefenition is MethodDefinition))
return;
- MethodDefinition mbase = (MethodDefinition) memberDefenition;
+ MethodDefinition mbase = (MethodDefinition)memberDefenition;
+
+ ParameterData parms = new ParameterData (writer, mbase.Parameters) {
+ HasExtensionParameter = mbase.CustomAttributes.Any (l => l.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute")
+ };
- ParameterData parms = new ParameterData (writer, mbase.Parameters);
parms.DoOutput ();
MemberData.OutputGenericParameters (writer, mbase);
this.parameters = parameters;
}
+ public bool HasExtensionParameter { get; set; }
+
public override void DoOutput ()
{
+ bool first = true;
writer.WriteStartElement ("parameters");
foreach (ParameterDefinition parameter in parameters) {
writer.WriteStartElement ("parameter");
AddAttribute ("position", parameter.Method.Parameters.IndexOf(parameter).ToString(CultureInfo.InvariantCulture));
AddAttribute ("attrib", ((int) parameter.Attributes).ToString());
- string direction = "in";
+ string direction = first && HasExtensionParameter ? "this" : "in";
+ first = false;
if (parameter.ParameterType is ByReferenceType)
direction = parameter.IsOut ? "out" : "ref";
static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly)
{
- return new FileInfo (assembly.MainModule.FullyQualifiedName);
+ return new FileInfo (assembly.MainModule.FileName);
}
static void CopyAssembly (FileInfo fi, string directory, bool symbols)
Annotations.Mark (type);
+ if (type.IsNested) {
+ var parent = type;
+ while (parent.IsNested) {
+ parent = parent.DeclaringType;
+ Annotations.Mark (parent);
+ }
+ }
+
switch (preserve) {
case TypePreserve.Nothing:
if (!nav.HasChildren)
// at this stage reference might include things that can't be resolved
// and if it is (resolved) it needs to be kept only if marked (#16213)
if ((td != null) && Annotations.IsMarked (td)) {
- scope = assembly.MainModule.Import (td).Scope;
+ scope = assembly.MainModule.ImportReference (td).Scope;
if (tr.Scope != scope)
changes = true;
hash.Add (tr, scope);
var td = et.Resolve ();
IMetadataScope scope = et.Scope;
if ((td != null) && Annotations.IsMarked (td)) {
- scope = assembly.MainModule.Import (td).Scope;
+ scope = assembly.MainModule.ImportReference (td).Scope;
hash.Add (td, scope);
}
}
public void CacheAssembly (AssemblyDefinition assembly)
{
_assemblies [assembly.Name.Name] = assembly;
- base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FullyQualifiedName));
+ base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FileName));
}
}
}
if (_symbolReaderProvider != null) {
var symbolReader = _symbolReaderProvider.GetSymbolReader (
assembly.MainModule,
- assembly.MainModule.FullyQualifiedName);
+ assembly.MainModule.FileName);
_annotations.AddSymbolReader (assembly, symbolReader);
assembly.MainModule.ReadSymbols (symbolReader);
static bool custom_mode = true;
static string embedded_options = null;
static string runtime = null;
+ static Dictionary<string,string> environment = new Dictionary<string,string>();
static string [] i18n = new string [] {
"West",
""
case "--quiet":
quiet = true;
break;
+ case "-e":
+ case "--env":
+ if (i+1 == top) {
+ Help ();
+ return 1;
+ }
+ var env = args [++i];
+ var p = env.IndexOf ('=');
+ if (p == -1)
+ environment.Add (env, "");
+ else
+ environment.Add (env.Substring (0, p), env.Substring (p+1));
+ break;
default:
sources.Add (args [i]);
break;
package.Position = package.Position + (align - (package.Position % align));
}
+ public void AddStringPair (string entry, string key, string value)
+ {
+ var kbytes = Encoding.UTF8.GetBytes (key);
+ var vbytes = Encoding.UTF8.GetBytes (value);
+
+ Console.WriteLine ("ADDING {0} to {1}", key, value);
+ if (kbytes.Length > 255){
+ Console.WriteLine ("The key value can not exceed 255 characters: " + key);
+ Environment.Exit (1);
+ }
+
+ locations [entry] = Tuple.Create (package.Position, kbytes.Length+vbytes.Length+3);
+ package.WriteByte ((byte)kbytes.Length);
+ package.Write (kbytes, 0, kbytes.Length);
+ package.WriteByte (0);
+ package.Write (vbytes, 0, vbytes.Length);
+ package.WriteByte (0);
+ package.Position = package.Position + (align - (package.Position % align));
+ }
+
public void Dump ()
{
if (quiet)
maker.Add ("config_dir:", config_dir);
if (embedded_options != null)
maker.AddString ("options:", embedded_options);
+ if (environment.Count > 0){
+ foreach (var key in environment.Keys)
+ maker.AddStringPair ("env:" + key, key, environment [key]);
+ }
maker.Dump ();
maker.Close ();
return true;
" --options OPTIONS Embed the specified Mono command line options on target\n" +
" --runtime RUNTIME Manually specifies the Mono runtime to use\n" +
" --target-server URL Specified a server to download targets from, default is " + target_server + "\n" +
+ " --env KEY=VALUE Hardcodes an environment variable for the target\n" +
"\n" +
"--custom Builds a custom launcher, options for --custom\n" +
" -c Produce stub only, do not compile\n" +
if (i > 0)
change.Append (", ");
+ string mods_tgt = tgt [i].GetAttribute ("direction") ?? "";
+ string mods_src = src [i].GetAttribute ("direction") ?? "";
+
+ if (mods_tgt.Length > 0)
+ mods_tgt = mods_tgt + " ";
+
+ if (mods_src.Length > 0)
+ mods_src = mods_src + " ";
+
if (i >= srcCount) {
- change.AppendAdded (tgt [i].GetTypeName ("type") + " " + tgt [i].GetAttribute ("name"), true);
+ change.AppendAdded (mods_tgt + tgt [i].GetTypeName ("type") + " " + tgt [i].GetAttribute ("name"), true);
} else if (i >= tgtCount) {
- change.AppendRemoved (src [i].GetTypeName ("type") + " " + src [i].GetAttribute ("name"), true);
+ change.AppendRemoved (mods_src + src [i].GetTypeName ("type") + " " + src [i].GetAttribute ("name"), true);
} else {
var paramSourceType = src [i].GetTypeName ("type");
var paramTargetType = tgt [i].GetTypeName ("type");
var paramSourceName = src [i].GetAttribute ("name");
var paramTargetName = tgt [i].GetAttribute ("name");
+ if (mods_src != mods_tgt) {
+ change.AppendModified (mods_src, mods_tgt, true);
+ } else {
+ change.Append (mods_src);
+ }
+
if (paramSourceType != paramTargetType) {
change.AppendModified (paramSourceType, paramTargetType, true);
} else {
}
change.Append (" ");
if (paramSourceName != paramTargetName) {
- change.AppendModified (paramSourceName, paramTargetName, false);
+ change.AppendModified (paramSourceName, paramTargetName, true);
} else {
change.Append (paramSourceName);
}
return null;
}
- assemblyPath = (exeFiles.Length > 0)? exeFiles[0] : dllFiles[0];
+ assemblyPath = exeFiles.Length > 0 ? exeFiles[0] : dllFiles[0];
var locProvider = new AssemblyLocationProvider (assemblyPath, logger);
var dllFiles = Directory.GetFiles (dir, "*.dll");
var assemblies = exeFiles.Concat (dllFiles);
foreach (var assemblyPath in assemblies) {
- var mdbPath = assemblyPath + ".mdb";
- if (!File.Exists (mdbPath)) {
- logger.LogWarning ("Directory {0} contains {1} but no mdb {2}.", dir, Path.GetFileName (assemblyPath), Path.GetFileName (mdbPath));
- // assemblies without mdb files are useless
+
+ // TODO: Ignore embedded pdb
+ var symbolFile = GetSymbolFile (assemblyPath);
+
+ if (symbolFile == null) {
+ logger.LogWarning ("Directory {0} contains {1} but no debug symbols file was found.", dir, Path.GetFileName (assemblyPath));
+ // assemblies without debug symbols are useless
continue;
}
if (Directory.Exists (mvidDir)) {
try {
Directory.Delete (mvidDir, true);
- } catch (DirectoryNotFoundException e) {}
+ } catch (DirectoryNotFoundException) {}
}
Directory.CreateDirectory (mvidDir);
var mvidAssemblyPath = Path.Combine (mvidDir, Path.GetFileName (assemblyPath));
File.Copy (assemblyPath, mvidAssemblyPath);
- var mvidMdbPath = Path.Combine (mvidDir, Path.GetFileName (mdbPath));
- File.Copy (mdbPath, mvidMdbPath);
+ var mvidDebugPath = Path.Combine (mvidDir, Path.GetFileName (symbolFile));
+ File.Copy (symbolFile, mvidDebugPath);
// TODO create MVID dir for non main modules with links to main module MVID
}
}
}
+
+ static string GetSymbolFile (string assembly)
+ {
+ var pdbName = Path.ChangeExtension (assembly, "pdb");
+ if (File.Exists (pdbName))
+ return pdbName;
+
+ var mdbName = assembly + ".mdb";
+
+ if (File.Exists (mdbName))
+ return mdbName;
+
+ return null;
+ }
}
}
<Compile Include="symbolicate.cs" />\r
<Compile Include="Logger.cs" />\r
<Compile Include="StackFrameData.cs" />\r
- <Compile Include="StackTraceMetadata.cs" />\r
<Compile Include="SymbolManager.cs" />\r
<Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">\r
<Link>Options.cs</Link>\r
while (type != null) {
// does the type implements it itself
if (type.HasInterfaces) {
- foreach (TypeReference iface in type.Interfaces) {
- string fullname = (generic) ? iface.GetElementType ().FullName : iface.FullName;
+ foreach (var iface in type.Interfaces) {
+ string fullname = (generic) ? iface.InterfaceType.GetElementType ().FullName : iface.InterfaceType.FullName;
if (fullname == interfaceName)
return true;
//if not, then maybe one of its parent interfaces does
- if (Implements (iface.Resolve (), interfaceName, generic))
+ if (Implements (iface.InterfaceType.Resolve (), interfaceName, generic))
return true;
}
}
<FileWrites Include="$(TargetFrameworkMonikerAssemblyAttributesPath)" />
</ItemGroup>
- <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ <Target Name="_GenerateTargetFrameworkMonikerAttribute"
DependsOnTargets="PrepareForBuild;GetReferenceAssemblyPaths"
Inputs="$(MSBuildToolsPath)\Microsoft.Common.targets"
- Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)"
- Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
+ Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)">
<WriteLinesToFile
File="$(TargetFrameworkMonikerAssemblyAttributesPath)"
ContinueOnError="true"
Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''"
/>
+ </Target>
+
+ <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ DependsOnTargets="_GenerateTargetFrameworkMonikerAttribute"
+ Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
<ItemGroup Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''">
<Compile Include="$(TargetFrameworkMonikerAssemblyAttributesPath)"/>
<FileWrites Include="$(TargetFrameworkMonikerAssemblyAttributesPath)" />
</ItemGroup>
- <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ <Target Name="_GenerateTargetFrameworkMonikerAttribute"
DependsOnTargets="PrepareForBuild;GetReferenceAssemblyPaths"
Inputs="$(MSBuildToolsPath)\Microsoft.Common.targets"
- Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)"
- Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
+ Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)">
<WriteLinesToFile
File="$(TargetFrameworkMonikerAssemblyAttributesPath)"
ContinueOnError="true"
Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''"
/>
+ </Target>
+
+ <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ DependsOnTargets="_GenerateTargetFrameworkMonikerAttribute"
+ Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
<ItemGroup Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''">
<Compile Include="$(TargetFrameworkMonikerAssemblyAttributesPath)"/>
<FileWrites Include="$(TargetFrameworkMonikerAssemblyAttributesPath)" />
</ItemGroup>
- <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ <Target Name="_GenerateTargetFrameworkMonikerAttribute"
DependsOnTargets="PrepareForBuild;GetReferenceAssemblyPaths"
Inputs="$(MSBuildToolsPath)\Microsoft.Common.targets"
- Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)"
- Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
+ Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)">
<WriteLinesToFile
File="$(TargetFrameworkMonikerAssemblyAttributesPath)"
ContinueOnError="true"
Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''"
/>
+ </Target>
+
+ <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ DependsOnTargets="_GenerateTargetFrameworkMonikerAttribute"
+ Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
<ItemGroup Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''">
<Compile Include="$(TargetFrameworkMonikerAssemblyAttributesPath)"/>
case EXDEV:
/* Ignore here, it is dealt with below */
break;
-
+
+ case ENOENT:
+ /* We already know src exists. Must be dest that doesn't exist. */
+ _wapi_set_last_path_error_from_errno (NULL, utf8_dest_name);
+ break;
+
default:
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ _wapi_set_last_error_from_errno ();
}
}
#define DEBUG_PROCESS 0x00000001
#define DEBUG_ONLY_THIS_PROCESS 0x00000002
-#define CREATE_SUSPENDED 0x00000004
#define DETACHED_PROCESS 0x00000008
#define CREATE_NEW_CONSOLE 0x00000010
#define NORMAL_PRIORITY_CLASS 0x00000020
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/mono-time.h>
#include <mono/utils/w32handle.h>
-#include <mono/utils/mono-threads.h>
-
-static gboolean own_if_signalled(gpointer handle)
-{
- gboolean ret = FALSE;
-
- if (mono_w32handle_issignalled (handle)) {
- mono_w32handle_ops_own (handle);
- ret = TRUE;
- }
-
- return(ret);
-}
-
-static gboolean own_if_owned(gpointer handle)
-{
- gboolean ret = FALSE;
-
- if (mono_w32handle_ops_isowned (handle)) {
- mono_w32handle_ops_own (handle);
- ret = TRUE;
- }
-
- return(ret);
-}
/**
* WaitForSingleObjectEx:
* @handle's state is still not signalled. %WAIT_FAILED - an error
* occurred. %WAIT_IO_COMPLETION - the wait was ended by an APC.
*/
-guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
- gboolean alertable)
-{
- guint32 ret, waited;
- int thr_ret;
- gboolean apc_pending = FALSE;
- gint64 wait_start, timeout_in_ticks;
-
- if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(WAIT_FAILED);
- }
-
- if (mono_w32handle_test_capabilities (handle,
- MONO_W32HANDLE_CAP_WAIT) == FALSE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p can't be waited for", __func__,
- handle);
-
- return(WAIT_FAILED);
- }
-
- mono_w32handle_ops_prewait (handle);
-
- if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p has special wait", __func__, handle);
-
- ret = mono_w32handle_ops_specialwait (handle, timeout, alertable ? &apc_pending : NULL);
-
- if (apc_pending)
- ret = WAIT_IO_COMPLETION;
-
- return ret;
- }
-
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, handle);
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (mono_w32handle_test_capabilities (handle,
- MONO_W32HANDLE_CAP_OWN) == TRUE) {
- if (own_if_owned (handle) == TRUE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
- handle);
- ret = WAIT_OBJECT_0;
- goto done;
- }
- }
-
- if (own_if_signalled (handle) == TRUE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__,
- handle);
-
- ret=WAIT_OBJECT_0;
- goto done;
- }
-
- if (timeout == 0) {
- ret = WAIT_TIMEOUT;
- goto done;
- }
-
- if (timeout != INFINITE) {
- wait_start = mono_100ns_ticks ();
- timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
- }
-
- do {
- /* Check before waiting on the condition, just in case
- */
- mono_w32handle_ops_prewait (handle);
-
- if (own_if_signalled (handle)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
- handle);
-
- ret = WAIT_OBJECT_0;
- goto done;
- }
-
- if (timeout == INFINITE) {
- waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &apc_pending : NULL);
- } else {
- gint64 elapsed = mono_100ns_ticks () - wait_start;
- if (elapsed >= timeout_in_ticks) {
- ret = WAIT_TIMEOUT;
- goto done;
- }
-
- waited = mono_w32handle_timedwait_signal_handle (handle, (timeout_in_ticks - elapsed) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
- }
-
- if(waited==0 && !apc_pending) {
- /* Condition was signalled, so hopefully
- * handle is signalled now. (It might not be
- * if someone else got in before us.)
- */
- if (own_if_signalled (handle)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
- handle);
-
- ret=WAIT_OBJECT_0;
- goto done;
- }
-
- /* Better luck next time */
- }
- } while(waited == 0 && !apc_pending);
-
- /* Timeout or other error */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, handle,
- strerror (waited));
-
- ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
-
-done:
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return(ret);
-}
-
-guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
+guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, gboolean alertable)
{
- return WaitForSingleObjectEx (handle, timeout, FALSE);
+ MonoW32HandleWaitRet ret;
+
+ ret = mono_w32handle_wait_one (handle, timeout, alertable);
+ if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
+ return WAIT_OBJECT_0;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
+ return WAIT_IO_COMPLETION;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
+ return WAIT_TIMEOUT;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED)
+ return WAIT_FAILED;
+ else
+ g_error ("%s: unknown ret value %d", __func__, ret);
}
guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
guint32 timeout, gboolean alertable)
{
- guint32 ret = 0, waited;
- int thr_ret;
- gboolean apc_pending = FALSE;
- gint64 wait_start, timeout_in_ticks;
-
- if ((GPOINTER_TO_UINT (signal_handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(WAIT_FAILED);
- }
-
- if ((GPOINTER_TO_UINT (wait) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(WAIT_FAILED);
- }
-
- if (mono_w32handle_test_capabilities (signal_handle,
- MONO_W32HANDLE_CAP_SIGNAL)==FALSE) {
- return(WAIT_FAILED);
- }
-
- if (mono_w32handle_test_capabilities (wait,
- MONO_W32HANDLE_CAP_WAIT)==FALSE) {
- return(WAIT_FAILED);
- }
-
- mono_w32handle_ops_prewait (wait);
-
- if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
- g_warning ("%s: handle %p has special wait, implement me!!",
- __func__, wait);
-
- return (WAIT_FAILED);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, wait);
-
- thr_ret = mono_w32handle_lock_handle (wait);
- g_assert (thr_ret == 0);
-
- mono_w32handle_ops_signal (signal_handle);
-
- if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_OWN)==TRUE) {
- if (own_if_owned (wait)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
- wait);
- ret = WAIT_OBJECT_0;
- goto done;
- }
- }
-
- if (own_if_signalled (wait)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__, wait);
-
- ret = WAIT_OBJECT_0;
- goto done;
- }
-
- if (timeout != INFINITE) {
- wait_start = mono_100ns_ticks ();
- timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
- }
- do {
- /* Check before waiting on the condition, just in case
- */
- mono_w32handle_ops_prewait (wait);
-
- if (own_if_signalled (wait)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, wait);
-
- ret = WAIT_OBJECT_0;
- goto done;
- }
-
- if (timeout == INFINITE) {
- waited = mono_w32handle_timedwait_signal_handle (wait, INFINITE, FALSE, alertable ? &apc_pending : NULL);
- } else {
- gint64 elapsed = mono_100ns_ticks () - wait_start;
- if (elapsed >= timeout_in_ticks) {
- ret = WAIT_TIMEOUT;
- goto done;
- }
-
- waited = mono_w32handle_timedwait_signal_handle (wait, (timeout_in_ticks - elapsed) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
- }
-
- if (waited==0 && !apc_pending) {
- /* Condition was signalled, so hopefully
- * handle is signalled now. (It might not be
- * if someone else got in before us.)
- */
- if (own_if_signalled (wait)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
- wait);
-
- ret = WAIT_OBJECT_0;
- goto done;
- }
-
- /* Better luck next time */
- }
- } while(waited == 0 && !apc_pending);
-
- /* Timeout or other error */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, wait, strerror (ret));
-
- ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
-
-done:
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, wait);
-
- thr_ret = mono_w32handle_unlock_handle (wait);
- g_assert (thr_ret == 0);
-
- return(ret);
-}
-
-static gboolean test_and_own (guint32 numobjects, gpointer *handles,
- gboolean waitall, guint32 *count,
- guint32 *lowest)
-{
- gboolean done;
- int i;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handles", __func__);
-
- done = mono_w32handle_count_signalled_handles (numobjects, handles,
- waitall, count, lowest);
- if (done == TRUE) {
- if (waitall == TRUE) {
- for (i = 0; i < numobjects; i++) {
- own_if_signalled (handles[i]);
- }
- } else {
- own_if_signalled (handles[*lowest]);
- }
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handles", __func__);
-
- mono_w32handle_unlock_handles (numobjects, handles);
-
- return(done);
+ MonoW32HandleWaitRet ret;
+
+ ret = mono_w32handle_signal_and_wait (signal_handle, wait, timeout, alertable);
+ if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
+ return WAIT_OBJECT_0;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
+ return WAIT_IO_COMPLETION;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
+ return WAIT_TIMEOUT;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED)
+ return WAIT_FAILED;
+ else
+ g_error ("%s: unknown ret value %d", __func__, ret);
}
/**
gboolean waitall, guint32 timeout,
gboolean alertable)
{
- gboolean duplicate = FALSE, bogustype = FALSE, done;
- guint32 count, lowest;
- guint i;
- guint32 ret;
- int thr_ret;
- guint32 retval;
- gboolean poll;
- gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
- gboolean apc_pending = FALSE;
- gint64 wait_start, timeout_in_ticks;
-
- if (numobjects > MAXIMUM_WAIT_OBJECTS) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Too many handles: %d", __func__, numobjects);
-
- return(WAIT_FAILED);
- }
-
- if (numobjects == 1) {
- return WaitForSingleObjectEx (handles [0], timeout, alertable);
- }
-
- /* Check for duplicates */
- for (i = 0; i < numobjects; i++) {
- if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %d pseudo process", __func__,
- i);
-
- bogustype = TRUE;
- break;
- }
-
- if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT) == FALSE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p can't be waited for",
- __func__, handles[i]);
-
- bogustype = TRUE;
- break;
- }
-
- sorted_handles [i] = handles [i];
- mono_w32handle_ops_prewait (handles[i]);
- }
-
- qsort (sorted_handles, numobjects, sizeof (gpointer), g_direct_equal);
- for (i = 1; i < numobjects; i++) {
- if (sorted_handles [i - 1] == sorted_handles [i]) {
- duplicate = TRUE;
- break;
- }
- }
-
- if (duplicate == TRUE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to duplicates", __func__);
-
- return(WAIT_FAILED);
- }
-
- if (bogustype == TRUE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to bogus type", __func__);
-
- return(WAIT_FAILED);
- }
-
- poll = FALSE;
- for (i = 0; i < numobjects; ++i)
- if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS)
- /* Can't wait for a process handle + another handle without polling */
- poll = TRUE;
-
- done = test_and_own (numobjects, handles, waitall, &count, &lowest);
- if (done == TRUE) {
- return(WAIT_OBJECT_0+lowest);
- }
-
- if (timeout == 0) {
+ MonoW32HandleWaitRet ret;
+
+ ret = mono_w32handle_wait_multiple (handles, numobjects, waitall, timeout, alertable);
+ if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
+ return WAIT_OBJECT_0 + (ret - MONO_W32HANDLE_WAIT_RET_SUCCESS_0);
+ else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
+ return WAIT_IO_COMPLETION;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
return WAIT_TIMEOUT;
- }
-
- if (timeout != INFINITE) {
- wait_start = mono_100ns_ticks ();
- timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
- }
-
- /* Have to wait for some or all handles to become signalled
- */
-
- for (i = 0; i < numobjects; i++) {
- /* Add a reference, as we need to ensure the handle wont
- * disappear from under us while we're waiting in the loop
- * (not lock, as we don't want exclusive access here)
- */
- mono_w32handle_ref (handles[i]);
- }
-
- while(1) {
- /* Prod all handles with prewait methods and
- * special-wait handles that aren't already signalled
- */
- for (i = 0; i < numobjects; i++) {
- mono_w32handle_ops_prewait (handles[i]);
-
- if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE && mono_w32handle_issignalled (handles[i]) == FALSE) {
- mono_w32handle_ops_specialwait (handles[i], 0, alertable ? &apc_pending : NULL);
- }
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking signal mutex", __func__);
-
- thr_ret = mono_w32handle_lock_signal_mutex ();
- g_assert (thr_ret == 0);
-
- /* Check the signalled state of handles inside the critical section */
- if (waitall) {
- done = TRUE;
- for (i = 0; i < numobjects; i++)
- if (!mono_w32handle_issignalled (handles [i]))
- done = FALSE;
- } else {
- done = FALSE;
- for (i = 0; i < numobjects; i++)
- if (mono_w32handle_issignalled (handles [i]))
- done = TRUE;
- }
-
- if (!done) {
- /* Enter the wait */
- if (timeout == INFINITE) {
- ret = mono_w32handle_timedwait_signal (INFINITE, poll, &apc_pending);
- } else {
- gint64 elapsed = mono_100ns_ticks () - wait_start;
- if (elapsed >= timeout_in_ticks) {
- ret = WAIT_TIMEOUT;
- } else {
- ret = mono_w32handle_timedwait_signal ((timeout_in_ticks - elapsed) / 10 / 1000, poll, &apc_pending);
- }
- }
- } else {
- /* No need to wait */
- ret = 0;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking signal mutex", __func__);
-
- thr_ret = mono_w32handle_unlock_signal_mutex ();
- g_assert (thr_ret == 0);
-
- if (alertable && apc_pending) {
- retval = WAIT_IO_COMPLETION;
- break;
- }
-
- /* Check if everything is signalled, as we can't
- * guarantee to notice a shared signal even if the
- * wait timed out
- */
- done = test_and_own (numobjects, handles, waitall,
- &count, &lowest);
- if (done == TRUE) {
- retval = WAIT_OBJECT_0+lowest;
- break;
- } else if (ret != 0) {
- /* Didn't get all handles, and there was a timeout */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait returned error: %s", __func__,
- strerror (ret));
-
- retval = WAIT_TIMEOUT;
- break;
- }
- }
-
- for (i = 0; i < numobjects; i++) {
- /* Unref everything we reffed above */
- mono_w32handle_unref (handles[i]);
- }
-
- return retval;
-}
-
-guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
- gboolean waitall, guint32 timeout)
-{
- return WaitForMultipleObjectsEx(numobjects, handles, waitall, timeout, FALSE);
-}
-
-/**
- * WaitForInputIdle:
- * @handle: a handle to the process to wait for
- * @timeout: the maximum time in milliseconds to wait for
- *
- * This function returns when either @handle process is waiting
- * for input, or @timeout ms elapses. If @timeout is zero, the
- * process state is tested and the function returns immediately.
- * If @timeout is %INFINITE, the function waits forever.
- *
- * Return value: 0 - @handle process is waiting for input.
- * %WAIT_TIMEOUT - The @timeout interval elapsed and
- * @handle process is not waiting for input. %WAIT_FAILED - an error
- * occurred.
- */
-guint32 WaitForInputIdle(gpointer handle, guint32 timeout)
-{
- /*TODO: Not implemented*/
- return WAIT_TIMEOUT;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED)
+ return WAIT_FAILED;
+ else
+ g_error ("%s: unknown ret value %d", __func__, ret);
}
#define _WAPI_WAIT_H_
#include "mono/io-layer/status.h"
+#include "mono/utils/w32handle.h"
G_BEGIN_DECLS
-#define MAXIMUM_WAIT_OBJECTS 64
-
#define INFINITE 0xFFFFFFFF
#define WAIT_FAILED 0xFFFFFFFF
#define WAIT_TIMEOUT STATUS_TIMEOUT
#define WAIT_IO_COMPLETION STATUS_USER_APC
-extern guint32 WaitForSingleObject(gpointer handle, guint32 timeout);
extern guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
gboolean alertable);
extern guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
guint32 timeout, gboolean alertable);
-extern guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
- gboolean waitall, guint32 timeout);
extern guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
gboolean waitall, guint32 timeout, gboolean alertable);
-extern guint32 WaitForInputIdle(gpointer handle, guint32 timeout);
G_END_DECLS
#endif /* _WAPI_WAIT_H_ */
#define GetFileVersionInfo wapi_GetFileVersionInfo
#define VerQueryValue wapi_VerQueryValue
#define VerLanguageName wapi_VerLanguageName
-#define WaitForSingleObject wapi_WaitForSingleObject
#define WaitForSingleObjectEx wapi_WaitForSingleObjectEx
#define SignalObjectAndWait wapi_SignalObjectAndWait
-#define WaitForMultipleObjects wapi_WaitForMultipleObjects
#define WaitForMultipleObjectsEx wapi_WaitForMultipleObjectsEx
-#define WaitForInputIdle wapi_WaitForInputIdle
#endif /* __WAPI_REMAP_H__ */
verify.c \
verify-internals.h \
wrapper-types.h \
+ dynamic-image-internals.h \
+ dynamic-stream.c \
+ dynamic-stream-internals.h \
+ reflection-cache.h \
+ custom-attrs-internals.h \
+ sre-internals.h \
reflection-internals.h \
file-mmap-posix.c \
file-mmap-windows.c \
monitor.c \
mono-hash.c \
object.c \
+ dynamic-image.c \
+ sre.c \
+ sre-encode.c \
+ sre-save.c \
+ custom-attrs.c \
reflection.c
+
boehm_sources = \
boehm-gc.c
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 152
+#define MONO_CORLIB_VERSION 154
typedef struct
{
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)
{
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;
}
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);
MonoAssembly *ass;
MonoAssemblyName aname;
MonoReflectionAssembly *refass = NULL;
- gchar *name;
+ gchar *name = NULL;
gboolean parsed;
g_assert (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;
}
/* 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)
+ if (!refOnly && prevent_running_reference_assembly (ass, &error))
+ goto leave;
+
+ g_assert (ass);
+ if (refass == NULL) {
refass = mono_assembly_get_object_checked (domain, ass, &error);
+ if (!is_ok (&error))
+ goto leave;
+ }
- if (refass == NULL)
- mono_error_set_pending_exception (&error);
- else
- MONO_OBJECT_SETREF (refass, evidence, evidence);
+ MONO_OBJECT_SETREF (refass, evidence, evidence);
+
+leave:
+ g_free (name);
+ mono_error_set_pending_exception (&error);
return refass;
}
*/
tp.priority = MONO_THREAD_PRIORITY_NORMAL;
tp.stack_size = 0;
- tp.creation_flags = CREATE_SUSPENDED;
+ tp.creation_flags = 0;
thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, &tp, &tid);
if (thread_handle == NULL)
return;
- mono_thread_info_resume (tid);
/* Wait for the thread */
while (!thread_data->done && guarded_wait (thread_handle, INFINITE, TRUE) == WAIT_IO_COMPLETION) {
if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) {
/* The unload thread tries to abort us */
/* The icall wrapper will execute the abort */
- CloseHandle (thread_handle);
unload_data_unref (thread_data);
return;
}
}
- CloseHandle (thread_handle);
if (thread_data->failure_reason) {
/* Roll back the state change */
/* Class lazy loading functions */
static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (reference_assembly, System.Runtime.CompilerServices, ReferenceAssemblyAttribute)
static MonoAssembly*
mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
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);
+
+ } else if (!image->assembly->ref_only) {
+ MonoError error;
+ if (mono_assembly_get_reference_assembly_attribute (reference, &error)) {
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following reference assembly assembly referenced from %s was not loaded. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context:\n"
+ " Assembly: %s (assemblyref_index=%d)\n"
+ " Version: %d.%d.%d.%d\n"
+ " Public Key: %s\n",
+ 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);
+ reference = NULL; /* don't load reference assemblies for execution */
+ }
+ if (!is_ok (&error)) {
+ reference = NULL;
+ mono_error_cleanup (&error);
+ }
}
mono_assemblies_lock ();
mono_assemblies_unlock ();
}
+
+/**
+ * mono_assembly_get_reference_assembly_attribute:
+ * @assembly: a MonoAssembly
+ * @error: set on error.
+ *
+ * Returns TRUE if @assembly has the System.Runtime.CompilerServices.ReferenceAssemblyAttribute set.
+ * On error returns FALSE and sets @error.
+ */
+gboolean
+mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
+{
+ mono_error_init (error);
+
+ MonoCustomAttrInfo *attrs = mono_custom_attrs_from_assembly_checked (assembly, error);
+ return_val_if_nok (error, FALSE);
+ if (!attrs)
+ return FALSE;
+ MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
+ gboolean result = FALSE;
+ for (int i = 0; i < attrs->num_attrs; ++i) {
+ MonoCustomAttrEntry *attr = &attrs->attrs [i];
+ if (attr->ctor && attr->ctor->klass && attr->ctor->klass == ref_asm_class) {
+ result = TRUE;
+ break;
+ }
+ }
+ mono_custom_attrs_free (attrs);
+ return result;
+}
+
/**
* mono_assembly_open:
* @filename: Opens the assembly pointed out by this name
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/handle.h>
#include <mono/metadata/sgen-toggleref.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-logger-internals.h>
res = GC_register_my_thread (&sb);
if (res == GC_UNIMPLEMENTED)
return NULL; /* Cannot happen with GC v7+. */
+
+ info->handle_stack = mono_handle_stack_alloc ();
+
return info;
}
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:
case MONO_GC_EVENT_POST_START_WORLD:
MONO_GC_WORLD_RESTART_END (1);
- mono_thread_info_suspend_unlock ();
break;
case MONO_GC_EVENT_START:
}
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)
return 0;
}
-gboolean
+MonoBoolean
mono_gc_pending_finalizers (void)
{
return GC_should_invoke_finalizers ();
}
}
-
+#else
+ #ifdef _MSC_VER
+ // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+ void __mono_win32_boehm_gc_quiet_lnk4221(void) {}
+ #endif
#endif /* no Boehm GC */
struct _MonoGenericClass {
MonoClass *container_class; /* the generic type definition */
MonoGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */ /* FIXME: Only the class_inst member of "context" is ever used, so this field could be replaced with just a monogenericinst */
- guint is_dynamic : 1; /* We're a MonoDynamicGenericClass */
+ guint is_dynamic : 1; /* Contains dynamic types */
guint is_tb_open : 1; /* This is the fully open instantiation for a type_builder. Quite ugly, but it's temporary.*/
+ guint need_sync : 1; /* Only if dynamic. Need to be synchronized with its container class after its finished. */
MonoClass *cached_class; /* if present, the MonoClass corresponding to the instantiation. */
/*
MonoImageSet *owner;
};
-/*
- * This is used when instantiating a generic type definition which is
- * a TypeBuilder.
- */
-struct _MonoDynamicGenericClass {
- MonoGenericClass generic_class;
- int count_fields;
- MonoClassField *fields;
- guint initialized;
- /* The non-inflated types of the fields */
- MonoType **field_generic_types;
- /* The managed objects representing the fields */
- MonoObject **field_objects;
-};
-
/*
* A type parameter.
*/
/* set the parent to something useful and safe, but mark the type as broken */
parent = mono_defaults.object_class;
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ g_assert (parent);
}
klass->parent = parent;
--- /dev/null
+#ifndef __MONO_METADATA_CUSTOM_ATTRS_INTERNALS_H__
+#define __MONO_METADATA_CUSTOM_ATTRS_INTERNALS_H__
+
+#include <mono/metadata/object.h>
+#include <mono/metadata/reflection.h>
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs);
+
+#endif /* __MONO_METADATA_REFLECTION_CUSTOM_ATTRS_INTERNALS_H__ */
--- /dev/null
+/*
+ * custom-attrs.c: Custom attributes.
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include "mono/metadata/gc-internals.h"
+#include "mono/metadata/mono-endian.h"
+#include "mono/metadata/object-internals.h"
+#include "mono/metadata/reflection-cache.h"
+#include "mono/metadata/custom-attrs-internals.h"
+#include "mono/metadata/sre-internals.h"
+#include "mono/metadata/reflection-internals.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/tokentype.h"
+#include "mono/metadata/verify-internals.h"
+#include "mono/utils/checked-build.h"
+
+
+#define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
+#define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
+
+#if SIZEOF_VOID_P == 4
+#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
+#else
+#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
+#endif
+
+#define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
+#define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
+
+static gboolean type_is_reference (MonoType *type);
+
+static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
+static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
+
+/*
+ * LOCKING: Acquires the loader lock.
+ */
+static MonoCustomAttrInfo*
+lookup_custom_attr (MonoImage *image, gpointer member)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ MonoCustomAttrInfo* res;
+
+ res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
+
+ if (!res)
+ return NULL;
+
+ res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
+ res->cached = 0;
+ return res;
+}
+
+static gboolean
+custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ /* FIXME: Need to do more checks */
+ if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
+ int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+
+ if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+type_is_reference (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_VALUETYPE:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static void
+free_param_data (MonoMethodSignature *sig, void **params) {
+ int i;
+ for (i = 0; i < sig->param_count; ++i) {
+ if (!type_is_reference (sig->params [i]))
+ g_free (params [i]);
+ }
+}
+
+/*
+ * Find the field index in the metadata FieldDef table.
+ */
+static guint32
+find_field_index (MonoClass *klass, MonoClassField *field) {
+ int i;
+
+ for (i = 0; i < klass->field.count; ++i) {
+ if (field == &klass->fields [i])
+ return klass->field.first + 1 + i;
+ }
+ return 0;
+}
+
+/*
+ * Find the property index in the metadata Property table.
+ */
+static guint32
+find_property_index (MonoClass *klass, MonoProperty *property) {
+ int i;
+
+ for (i = 0; i < klass->ext->property.count; ++i) {
+ if (property == &klass->ext->properties [i])
+ return klass->ext->property.first + 1 + i;
+ }
+ return 0;
+}
+
+/*
+ * Find the event index in the metadata Event table.
+ */
+static guint32
+find_event_index (MonoClass *klass, MonoEvent *event) {
+ int i;
+
+ for (i = 0; i < klass->ext->event.count; ++i) {
+ if (event == &klass->ext->events [i])
+ return klass->ext->event.first + 1 + i;
+ }
+ return 0;
+}
+
+/*
+ * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
+ * The @is_enum flag only affects the error message that's displayed on failure.
+ */
+static MonoType*
+cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
+{
+ MonoError inner_error;
+ MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
+ if (!t) {
+ mono_error_set_type_load_name (error, g_strdup(n), NULL,
+ "Could not load %s %s while decoding custom attribute: %s",
+ is_enum ? "enum type": "type",
+ n,
+ mono_error_get_message (&inner_error));
+ mono_error_cleanup (&inner_error);
+ return NULL;
+ }
+ return t;
+}
+
+static MonoClass*
+load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
+{
+ char *n;
+ MonoType *t;
+ int slen = mono_metadata_decode_value (p, &p);
+
+ mono_error_init (error);
+
+ n = (char *)g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = cattr_type_from_name (n, image, TRUE, error);
+ g_free (n);
+ return_val_if_nok (error, NULL);
+ p += slen;
+ *end = p;
+ return mono_class_from_mono_type (t);
+}
+
+static void*
+load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
+{
+ int slen, type = t->type;
+ MonoClass *tklass = t->data.klass;
+
+ mono_error_init (error);
+
+handle_enum:
+ switch (type) {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
+ *bval = *p;
+ *end = p + 1;
+ return bval;
+ }
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2: {
+ guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
+ *val = read16 (p);
+ *end = p + 2;
+ return val;
+ }
+#if SIZEOF_VOID_P == 4
+ case MONO_TYPE_U:
+ case MONO_TYPE_I:
+#endif
+ case MONO_TYPE_R4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4: {
+ guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
+ *val = read32 (p);
+ *end = p + 4;
+ return val;
+ }
+#if SIZEOF_VOID_P == 8
+ case MONO_TYPE_U: /* error out instead? this should probably not happen */
+ case MONO_TYPE_I:
+#endif
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8: {
+ guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
+ *val = read64 (p);
+ *end = p + 8;
+ return val;
+ }
+ case MONO_TYPE_R8: {
+ double *val = (double *)g_malloc (sizeof (double));
+ readr8 (p, val);
+ *end = p + 8;
+ return val;
+ }
+ case MONO_TYPE_VALUETYPE:
+ if (t->data.klass->enumtype) {
+ type = mono_class_enum_basetype (t->data.klass)->type;
+ goto handle_enum;
+ } else {
+ MonoClass *k = t->data.klass;
+
+ if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
+ guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
+ *val = read64 (p);
+ *end = p + 8;
+ return val;
+ }
+ }
+ g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
+ break;
+
+ case MONO_TYPE_STRING:
+ if (*p == (char)0xFF) {
+ *end = p + 1;
+ return NULL;
+ }
+ slen = mono_metadata_decode_value (p, &p);
+ *end = p + slen;
+ return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
+ case MONO_TYPE_CLASS: {
+ MonoReflectionType *rt;
+ char *n;
+ MonoType *t;
+ if (*p == (char)0xFF) {
+ *end = p + 1;
+ return NULL;
+ }
+handle_type:
+ slen = mono_metadata_decode_value (p, &p);
+ n = (char *)g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = cattr_type_from_name (n, image, FALSE, error);
+ g_free (n);
+ return_val_if_nok (error, NULL);
+ *end = p + slen;
+
+ rt = mono_type_get_object_checked (mono_domain_get (), t, error);
+ if (!mono_error_ok (error))
+ return NULL;
+
+ return rt;
+ }
+ case MONO_TYPE_OBJECT: {
+ char subt = *p++;
+ MonoObject *obj;
+ MonoClass *subc = NULL;
+ void *val;
+
+ if (subt == 0x50) {
+ goto handle_type;
+ } else if (subt == 0x0E) {
+ type = MONO_TYPE_STRING;
+ goto handle_enum;
+ } else if (subt == 0x1D) {
+ MonoType simple_type = {{0}};
+ int etype = *p;
+ p ++;
+
+ type = MONO_TYPE_SZARRAY;
+ if (etype == 0x50) {
+ tklass = mono_defaults.systemtype_class;
+ } else if (etype == 0x55) {
+ tklass = load_cattr_enum_type (image, p, &p, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ } else {
+ if (etype == 0x51)
+ /* See Partition II, Appendix B3 */
+ etype = MONO_TYPE_OBJECT;
+ simple_type.type = (MonoTypeEnum)etype;
+ tklass = mono_class_from_mono_type (&simple_type);
+ }
+ goto handle_enum;
+ } else if (subt == 0x55) {
+ char *n;
+ MonoType *t;
+ slen = mono_metadata_decode_value (p, &p);
+ n = (char *)g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = cattr_type_from_name (n, image, FALSE, error);
+ g_free (n);
+ return_val_if_nok (error, NULL);
+ p += slen;
+ subc = mono_class_from_mono_type (t);
+ } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
+ MonoType simple_type = {{0}};
+ simple_type.type = (MonoTypeEnum)subt;
+ subc = mono_class_from_mono_type (&simple_type);
+ } else {
+ g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
+ }
+ val = load_cattr_value (image, &subc->byval_arg, p, end, error);
+ obj = NULL;
+ if (mono_error_ok (error)) {
+ obj = mono_object_new_checked (mono_domain_get (), subc, error);
+ g_assert (!subc->has_references);
+ if (mono_error_ok (error))
+ mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
+ }
+
+ g_free (val);
+ return obj;
+ }
+ case MONO_TYPE_SZARRAY: {
+ MonoArray *arr;
+ guint32 i, alen, basetype;
+ alen = read32 (p);
+ p += 4;
+ if (alen == 0xffffffff) {
+ *end = p;
+ return NULL;
+ }
+ arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
+ return_val_if_nok (error, NULL);
+ basetype = tklass->byval_arg.type;
+ if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
+ basetype = mono_class_enum_basetype (tklass)->type;
+ switch (basetype)
+ {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_BOOLEAN:
+ for (i = 0; i < alen; i++) {
+ MonoBoolean val = *p++;
+ mono_array_set (arr, MonoBoolean, i, val);
+ }
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ for (i = 0; i < alen; i++) {
+ guint16 val = read16 (p);
+ mono_array_set (arr, guint16, i, val);
+ p += 2;
+ }
+ break;
+ case MONO_TYPE_R4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ for (i = 0; i < alen; i++) {
+ guint32 val = read32 (p);
+ mono_array_set (arr, guint32, i, val);
+ p += 4;
+ }
+ break;
+ case MONO_TYPE_R8:
+ for (i = 0; i < alen; i++) {
+ double val;
+ readr8 (p, &val);
+ mono_array_set (arr, double, i, val);
+ p += 8;
+ }
+ break;
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ for (i = 0; i < alen; i++) {
+ guint64 val = read64 (p);
+ mono_array_set (arr, guint64, i, val);
+ p += 8;
+ }
+ break;
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_SZARRAY:
+ for (i = 0; i < alen; i++) {
+ MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ mono_array_setref (arr, i, item);
+ }
+ break;
+ default:
+ g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
+ }
+ *end=p;
+ return arr;
+ }
+ default:
+ g_error ("Type 0x%02x not handled in custom attr value decoding", type);
+ }
+ return NULL;
+}
+
+static MonoObject*
+load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
+{
+ mono_error_init (error);
+
+ gboolean is_ref = type_is_reference (t);
+
+ void *val = load_cattr_value (image, t, p, end, error);
+ if (!is_ok (error)) {
+ if (is_ref)
+ g_free (val);
+ return NULL;
+ }
+
+ if (is_ref)
+ return (MonoObject*)val;
+
+ MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
+ g_free (val);
+ return boxed;
+}
+
+static MonoObject*
+create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
+{
+ static MonoMethod *ctor;
+ MonoObject *retval;
+ void *params [2], *unboxed;
+
+ mono_error_init (error);
+
+ if (!ctor)
+ ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
+
+ params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
+ return_val_if_nok (error, NULL);
+
+ params [1] = val;
+ retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
+ return_val_if_nok (error, NULL);
+ unboxed = mono_object_unbox (retval);
+
+ mono_runtime_invoke_checked (ctor, unboxed, params, error);
+ return_val_if_nok (error, NULL);
+
+ return retval;
+}
+
+static MonoObject*
+create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
+{
+ static MonoMethod *ctor;
+ MonoObject *retval;
+ void *unboxed, *params [2];
+
+ mono_error_init (error);
+
+ if (!ctor)
+ ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
+
+ params [0] = minfo;
+ params [1] = typedarg;
+ retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
+ return_val_if_nok (error, NULL);
+
+ unboxed = mono_object_unbox (retval);
+
+ mono_runtime_invoke_checked (ctor, unboxed, params, error);
+ return_val_if_nok (error, NULL);
+
+ return retval;
+}
+
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ int i, index, count, not_visible;
+ MonoCustomAttrInfo *ainfo;
+ MonoReflectionCustomAttr *cattr;
+
+ if (!cattrs)
+ return NULL;
+ /* FIXME: check in assembly the Run flag is set */
+
+ count = mono_array_length (cattrs);
+
+ /* Skip nonpublic attributes since MS.NET seems to do the same */
+ /* FIXME: This needs to be done more globally */
+ not_visible = 0;
+ for (i = 0; i < count; ++i) {
+ cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+ if (!custom_attr_visible (image, cattr))
+ not_visible ++;
+ }
+
+ int num_attrs = count - not_visible;
+ ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
+
+ ainfo->image = image;
+ ainfo->num_attrs = num_attrs;
+ ainfo->cached = alloc_img != NULL;
+ index = 0;
+ for (i = 0; i < count; ++i) {
+ cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+ if (custom_attr_visible (image, cattr)) {
+ unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
+ memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
+ ainfo->attrs [index].ctor = cattr->ctor->method;
+ g_assert (cattr->ctor->method);
+ ainfo->attrs [index].data = saved;
+ ainfo->attrs [index].data_size = mono_array_length (cattr->data);
+ index ++;
+ }
+ }
+ g_assert (index == num_attrs && count == num_attrs + not_visible);
+
+ return ainfo;
+}
+
+
+static MonoObject*
+create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
+{
+ const char *p = (const char*)data;
+ const char *named;
+ guint32 i, j, num_named;
+ MonoObject *attr;
+ void *params_buf [32];
+ void **params = NULL;
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ mono_class_init (method->klass);
+
+ if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+ return NULL;
+ }
+
+ if (len == 0) {
+ attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
+ if (!mono_error_ok (error)) return NULL;
+
+ mono_runtime_invoke_checked (method, attr, NULL, error);
+ if (!mono_error_ok (error))
+ return NULL;
+
+ return attr;
+ }
+
+ if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+ return NULL;
+
+ /*g_print ("got attr %s\n", method->klass->name);*/
+
+ sig = mono_method_signature (method);
+ if (sig->param_count < 32) {
+ params = params_buf;
+ memset (params, 0, sizeof (void*) * sig->param_count);
+ } else {
+ /* Allocate using GC so it gets GC tracking */
+ params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
+ }
+
+ /* skip prolog */
+ p += 2;
+ for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+ params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
+ if (!mono_error_ok (error))
+ goto fail;
+ }
+
+ named = p;
+ attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
+ if (!mono_error_ok (error)) goto fail;
+
+ MonoObject *exc = NULL;
+ mono_runtime_try_invoke (method, attr, params, &exc, error);
+ if (!mono_error_ok (error))
+ goto fail;
+ if (exc) {
+ mono_error_set_exception_instance (error, (MonoException*)exc);
+ goto fail;
+ }
+
+ num_named = read16 (named);
+ named += 2;
+ for (j = 0; j < num_named; j++) {
+ gint name_len;
+ char *name, named_type, data_type;
+ named_type = *named++;
+ data_type = *named++; /* type of data */
+ if (data_type == MONO_TYPE_SZARRAY)
+ data_type = *named++;
+ if (data_type == MONO_TYPE_ENUM) {
+ gint type_len;
+ char *type_name;
+ type_len = mono_metadata_decode_blob_size (named, &named);
+ type_name = (char *)g_malloc (type_len + 1);
+ memcpy (type_name, named, type_len);
+ type_name [type_len] = 0;
+ named += type_len;
+ /* FIXME: lookup the type and check type consistency */
+ g_free (type_name);
+ }
+ name_len = mono_metadata_decode_blob_size (named, &named);
+ name = (char *)g_malloc (name_len + 1);
+ memcpy (name, named, name_len);
+ name [name_len] = 0;
+ named += name_len;
+ if (named_type == 0x53) {
+ MonoClassField *field;
+ void *val;
+
+ /* how this fail is a blackbox */
+ field = mono_class_get_field_from_name (mono_object_class (attr), name);
+ if (!field) {
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
+ g_free (name);
+ goto fail;
+ }
+
+ val = load_cattr_value (image, field->type, named, &named, error);
+ if (!mono_error_ok (error)) {
+ g_free (name);
+ if (!type_is_reference (field->type))
+ g_free (val);
+ goto fail;
+ }
+
+ mono_field_set_value (attr, field, val);
+ if (!type_is_reference (field->type))
+ g_free (val);
+ } else if (named_type == 0x54) {
+ MonoProperty *prop;
+ void *pparams [1];
+ MonoType *prop_type;
+
+ prop = mono_class_get_property_from_name (mono_object_class (attr), name);
+
+ if (!prop) {
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
+ g_free (name);
+ goto fail;
+ }
+
+ if (!prop->set) {
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
+ g_free (name);
+ goto fail;
+ }
+
+ /* can we have more that 1 arg in a custom attr named property? */
+ prop_type = prop->get? mono_method_signature (prop->get)->ret :
+ mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
+
+ pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
+ if (!mono_error_ok (error)) {
+ g_free (name);
+ if (!type_is_reference (prop_type))
+ g_free (pparams [0]);
+ goto fail;
+ }
+
+
+ mono_property_set_value_checked (prop, attr, pparams, error);
+ if (!type_is_reference (prop_type))
+ g_free (pparams [0]);
+ if (!is_ok (error)) {
+ g_free (name);
+ goto fail;
+ }
+ }
+ g_free (name);
+ }
+
+ free_param_data (method->signature, params);
+ if (params != params_buf)
+ mono_gc_free_fixed (params);
+
+ return attr;
+
+fail:
+ free_param_data (method->signature, params);
+ if (params != params_buf)
+ mono_gc_free_fixed (params);
+ return NULL;
+}
+
+/*
+ * mono_reflection_create_custom_attr_data_args:
+ *
+ * Create an array of typed and named arguments from the cattr blob given by DATA.
+ * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
+ * NAMED_ARG_INFO will contain information about the named arguments.
+ */
+void
+mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
+{
+ MonoArray *typedargs, *namedargs;
+ MonoClass *attrklass;
+ MonoDomain *domain;
+ const char *p = (const char*)data;
+ const char *named;
+ guint32 i, j, num_named;
+ CattrNamedArg *arginfo = NULL;
+
+ *typed_args = NULL;
+ *named_args = NULL;
+ *named_arg_info = NULL;
+
+ mono_error_init (error);
+
+ if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+ return;
+ }
+
+ mono_class_init (method->klass);
+
+ domain = mono_domain_get ();
+
+ if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+ return;
+
+ typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
+ return_if_nok (error);
+
+ /* skip prolog */
+ p += 2;
+ for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+ MonoObject *obj;
+
+ obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
+ return_if_nok (error);
+ mono_array_setref (typedargs, i, obj);
+ }
+
+ named = p;
+ num_named = read16 (named);
+ namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
+ return_if_nok (error);
+ named += 2;
+ attrklass = method->klass;
+
+ arginfo = g_new0 (CattrNamedArg, num_named);
+ *named_arg_info = arginfo;
+
+ for (j = 0; j < num_named; j++) {
+ gint name_len;
+ char *name, named_type, data_type;
+ named_type = *named++;
+ data_type = *named++; /* type of data */
+ if (data_type == MONO_TYPE_SZARRAY)
+ data_type = *named++;
+ if (data_type == MONO_TYPE_ENUM) {
+ gint type_len;
+ char *type_name;
+ type_len = mono_metadata_decode_blob_size (named, &named);
+ if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
+ goto fail;
+
+ type_name = (char *)g_malloc (type_len + 1);
+ memcpy (type_name, named, type_len);
+ type_name [type_len] = 0;
+ named += type_len;
+ /* FIXME: lookup the type and check type consistency */
+ g_free (type_name);
+ }
+ name_len = mono_metadata_decode_blob_size (named, &named);
+ if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
+ goto fail;
+ name = (char *)g_malloc (name_len + 1);
+ memcpy (name, named, name_len);
+ name [name_len] = 0;
+ named += name_len;
+ if (named_type == 0x53) {
+ MonoObject *obj;
+ MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
+
+ if (!field) {
+ g_free (name);
+ goto fail;
+ }
+
+ arginfo [j].type = field->type;
+ arginfo [j].field = field;
+
+ obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
+ if (!is_ok (error)) {
+ g_free (name);
+ return;
+ }
+ mono_array_setref (namedargs, j, obj);
+
+ } else if (named_type == 0x54) {
+ MonoObject *obj;
+ MonoType *prop_type;
+ MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
+
+ if (!prop || !prop->set) {
+ g_free (name);
+ goto fail;
+ }
+
+ prop_type = prop->get? mono_method_signature (prop->get)->ret :
+ mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
+
+ arginfo [j].type = prop_type;
+ arginfo [j].prop = prop;
+
+ obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
+ if (!is_ok (error)) {
+ g_free (name);
+ return;
+ }
+ mono_array_setref (namedargs, j, obj);
+ }
+ g_free (name);
+ }
+
+ *typed_args = typedargs;
+ *named_args = namedargs;
+ return;
+fail:
+ mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+ g_free (arginfo);
+ *named_arg_info = NULL;
+}
+
+static gboolean
+reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
+{
+ MonoDomain *domain;
+ MonoArray *typedargs, *namedargs;
+ MonoImage *image;
+ MonoMethod *method;
+ CattrNamedArg *arginfo = NULL;
+ int i;
+
+ mono_error_init (error);
+
+ *ctor_args = NULL;
+ *named_args = NULL;
+
+ if (len == 0)
+ return TRUE;
+
+ image = assembly->assembly->image;
+ method = ref_method->method;
+ domain = mono_object_domain (ref_method);
+
+ if (!mono_class_init (method->klass)) {
+ mono_error_set_for_class_failure (error, method->klass);
+ goto leave;
+ }
+
+ mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
+ if (!is_ok (error))
+ goto leave;
+
+ if (!typedargs || !namedargs)
+ goto leave;
+
+ for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+ MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
+ MonoObject *typedarg;
+
+ typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
+ if (!is_ok (error))
+ goto leave;
+ mono_array_setref (typedargs, i, typedarg);
+ }
+
+ for (i = 0; i < mono_array_length (namedargs); ++i) {
+ MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
+ MonoObject *typedarg, *namedarg, *minfo;
+
+ if (arginfo [i].prop) {
+ minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
+ if (!minfo)
+ goto leave;
+ } else {
+ minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
+ if (!is_ok (error))
+ goto leave;
+ }
+
+ typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
+ if (!is_ok (error))
+ goto leave;
+ namedarg = create_cattr_named_arg (minfo, typedarg, error);
+ if (!is_ok (error))
+ goto leave;
+
+ mono_array_setref (namedargs, i, namedarg);
+ }
+
+ *ctor_args = typedargs;
+ *named_args = namedargs;
+
+leave:
+ g_free (arginfo);
+ return mono_error_ok (error);
+}
+
+void
+ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
+{
+ MonoError error;
+ (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
+{
+ static MonoMethod *ctor;
+
+ MonoDomain *domain;
+ MonoObject *attr;
+ void *params [4];
+
+ mono_error_init (error);
+
+ g_assert (image->assembly);
+
+ if (!ctor)
+ ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
+
+ domain = mono_domain_get ();
+ attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
+ return_val_if_nok (error, NULL);
+ params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
+ return_val_if_nok (error, NULL);
+ params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
+ return_val_if_nok (error, NULL);
+ params [2] = (gpointer)&cattr->data;
+ params [3] = &cattr->data_size;
+
+ mono_runtime_invoke_checked (ctor, attr, params, error);
+ return_val_if_nok (error, NULL);
+ return attr;
+}
+
+static MonoArray*
+mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
+{
+ MonoArray *result;
+ MonoObject *attr;
+ int i, n;
+
+ mono_error_init (error);
+
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ MonoCustomAttrEntry *centry = &cinfo->attrs[i];
+ if (!centry->ctor) {
+ /* The cattr type is not finished yet */
+ /* We should include the type name but cinfo doesn't contain it */
+ mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
+ return NULL;
+ }
+ }
+
+ n = 0;
+ if (attr_klass) {
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ MonoMethod *ctor = cinfo->attrs[i].ctor;
+ g_assert (ctor);
+ if (mono_class_is_assignable_from (attr_klass, ctor->klass))
+ n++;
+ }
+ } else {
+ n = cinfo->num_attrs;
+ }
+
+ result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
+ return_val_if_nok (error, NULL);
+ n = 0;
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ MonoCustomAttrEntry *centry = &cinfo->attrs [i];
+ if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
+ attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
+ if (!mono_error_ok (error))
+ return result;
+ mono_array_setref (result, n, attr);
+ n ++;
+ }
+ }
+ return result;
+}
+
+MonoArray*
+mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+{
+ MonoError error;
+ MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
+ mono_error_assert_ok (&error); /*FIXME proper error handling*/
+
+ return result;
+}
+
+static MonoArray*
+mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
+{
+ MonoArray *result;
+ MonoObject *attr;
+ int i;
+
+ mono_error_init (error);
+ result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
+ return_val_if_nok (error, NULL);
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
+ return_val_if_nok (error, NULL);
+ mono_array_setref (result, i, attr);
+ }
+ return result;
+}
+
+/**
+ * mono_custom_attrs_from_index:
+ *
+ * Returns: NULL if no attributes are found or if a loading error occurs.
+ */
+MonoCustomAttrInfo*
+mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
+{
+ MonoError error;
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+/**
+ * mono_custom_attrs_from_index_checked:
+ *
+ * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
+ */
+MonoCustomAttrInfo*
+mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
+{
+ guint32 mtoken, i, len;
+ guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+ MonoTableInfo *ca;
+ MonoCustomAttrInfo *ainfo;
+ GList *tmp, *list = NULL;
+ const char *data;
+ MonoCustomAttrEntry* attr;
+
+ mono_error_init (error);
+
+ ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+
+ i = mono_metadata_custom_attrs_from_index (image, idx);
+ if (!i)
+ return NULL;
+ i --;
+ while (i < ca->rows) {
+ if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+ break;
+ list = g_list_prepend (list, GUINT_TO_POINTER (i));
+ ++i;
+ }
+ len = g_list_length (list);
+ if (!len)
+ return NULL;
+ ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
+ ainfo->num_attrs = len;
+ ainfo->image = image;
+ for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
+ mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
+ mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
+ case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
+ mtoken |= MONO_TOKEN_METHOD_DEF;
+ break;
+ case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
+ mtoken |= MONO_TOKEN_MEMBER_REF;
+ break;
+ default:
+ g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
+ break;
+ }
+ attr = &ainfo->attrs [i - 1];
+ attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
+ if (!attr->ctor) {
+ g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
+ g_list_free (list);
+ g_free (ainfo);
+ return NULL;
+ }
+
+ if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
+ /*FIXME raising an exception here doesn't make any sense*/
+ g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
+ g_list_free (list);
+ g_free (ainfo);
+ return NULL;
+ }
+ data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
+ attr->data_size = mono_metadata_decode_value (data, &data);
+ attr->data = (guchar*)data;
+ }
+ g_list_free (list);
+
+ return ainfo;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_method (MonoMethod *method)
+{
+ MonoError error;
+ MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
+ mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
+{
+ guint32 idx;
+
+ mono_error_init (error);
+
+ /*
+ * An instantiated method has the same cattrs as the generic method definition.
+ *
+ * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
+ * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
+ */
+ if (method->is_inflated)
+ method = ((MonoMethodInflated *) method)->declaring;
+
+ if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
+ return lookup_custom_attr (method->klass->image, method);
+
+ if (!method->token)
+ /* Synthetic methods */
+ return NULL;
+
+ idx = mono_method_get_index (method);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_METHODDEF;
+ return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_class (MonoClass *klass)
+{
+ MonoError error;
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
+{
+ guint32 idx;
+
+ mono_error_init (error);
+
+ if (klass->generic_class)
+ klass = klass->generic_class->container_class;
+
+ if (image_is_dynamic (klass->image))
+ return lookup_custom_attr (klass->image, klass);
+
+ if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
+ idx = mono_metadata_token_index (klass->sizes.generic_param_token);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_GENERICPAR;
+ } else {
+ idx = mono_metadata_token_index (klass->type_token);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_TYPEDEF;
+ }
+ return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_assembly (MonoAssembly *assembly)
+{
+ MonoError error;
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
+{
+ guint32 idx;
+
+ mono_error_init (error);
+
+ if (image_is_dynamic (assembly->image))
+ return lookup_custom_attr (assembly->image, assembly);
+ idx = 1; /* there is only one assembly */
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
+ return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
+}
+
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
+{
+ guint32 idx;
+
+ if (image_is_dynamic (image))
+ return lookup_custom_attr (image, image);
+ idx = 1; /* there is only one module */
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_MODULE;
+ return mono_custom_attrs_from_index_checked (image, idx, error);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
+{
+ MonoError error;
+ MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
+{
+ guint32 idx;
+
+ if (image_is_dynamic (klass->image)) {
+ property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
+ return lookup_custom_attr (klass->image, property);
+ }
+ idx = find_property_index (klass, property);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_PROPERTY;
+ return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
+{
+ MonoError error;
+ MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
+{
+ guint32 idx;
+
+ if (image_is_dynamic (klass->image)) {
+ event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
+ return lookup_custom_attr (klass->image, event);
+ }
+ idx = find_event_index (klass, event);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_EVENT;
+ return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
+{
+ MonoError error;
+ MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
+{
+ guint32 idx;
+ mono_error_init (error);
+
+ if (image_is_dynamic (klass->image)) {
+ field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
+ return lookup_custom_attr (klass->image, field);
+ }
+ idx = find_field_index (klass, field);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_FIELDDEF;
+ return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+}
+
+/**
+ * mono_custom_attrs_from_param:
+ * @method: handle to the method that we want to retrieve custom parameter information from
+ * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
+ *
+ * The result must be released with mono_custom_attrs_free().
+ *
+ * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
+ */
+MonoCustomAttrInfo*
+mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
+{
+ MonoError error;
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+/**
+ * mono_custom_attrs_from_param_checked:
+ * @method: handle to the method that we want to retrieve custom parameter information from
+ * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
+ * @error: set on error
+ *
+ * The result must be released with mono_custom_attrs_free().
+ *
+ * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
+ */
+MonoCustomAttrInfo*
+mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
+{
+ MonoTableInfo *ca;
+ guint32 i, idx, method_index;
+ guint32 param_list, param_last, param_pos, found;
+ MonoImage *image;
+ MonoReflectionMethodAux *aux;
+
+ mono_error_init (error);
+
+ /*
+ * An instantiated method has the same cattrs as the generic method definition.
+ *
+ * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
+ * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
+ */
+ if (method->is_inflated)
+ method = ((MonoMethodInflated *) method)->declaring;
+
+ if (image_is_dynamic (method->klass->image)) {
+ MonoCustomAttrInfo *res, *ainfo;
+ int size;
+
+ aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+ if (!aux || !aux->param_cattr)
+ return NULL;
+
+ /* Need to copy since it will be freed later */
+ ainfo = aux->param_cattr [param];
+ if (!ainfo)
+ return NULL;
+ size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
+ res = (MonoCustomAttrInfo *)g_malloc0 (size);
+ memcpy (res, ainfo, size);
+ return res;
+ }
+
+ image = method->klass->image;
+ method_index = mono_method_get_index (method);
+ if (!method_index)
+ return NULL;
+ ca = &image->tables [MONO_TABLE_METHOD];
+
+ param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
+ if (method_index == ca->rows) {
+ ca = &image->tables [MONO_TABLE_PARAM];
+ param_last = ca->rows + 1;
+ } else {
+ param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
+ ca = &image->tables [MONO_TABLE_PARAM];
+ }
+ found = FALSE;
+ for (i = param_list; i < param_last; ++i) {
+ param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
+ if (param_pos == param) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ return NULL;
+ idx = i;
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_PARAMDEF;
+ return mono_custom_attrs_from_index_checked (image, idx, error);
+}
+
+gboolean
+mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
+{
+ int i;
+ for (i = 0; i < ainfo->num_attrs; ++i) {
+ MonoClass *klass = ainfo->attrs [i].ctor->klass;
+ if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+MonoObject*
+mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
+{
+ MonoError error;
+ MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
+ mono_error_assert_ok (&error); /*FIXME proper error handling*/
+ return res;
+}
+
+MonoObject*
+mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
+{
+ int i, attr_index;
+ MonoArray *attrs;
+
+ mono_error_init (error);
+
+ attr_index = -1;
+ for (i = 0; i < ainfo->num_attrs; ++i) {
+ MonoClass *klass = ainfo->attrs [i].ctor->klass;
+ if (mono_class_has_parent (klass, attr_klass)) {
+ attr_index = i;
+ break;
+ }
+ }
+ if (attr_index == -1)
+ return NULL;
+
+ attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ return mono_array_get (attrs, MonoObject*, attr_index);
+}
+
+/*
+ * mono_reflection_get_custom_attrs_info:
+ * @obj: a reflection object handle
+ *
+ * Return the custom attribute info for attributes defined for the
+ * reflection handle @obj. The objects.
+ *
+ * FIXME this function leaks like a sieve for SRE objects.
+ */
+MonoCustomAttrInfo*
+mono_reflection_get_custom_attrs_info (MonoObject *obj)
+{
+ MonoError error;
+ MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
+
+/**
+ * mono_reflection_get_custom_attrs_info_checked:
+ * @obj: a reflection object handle
+ * @error: set on error
+ *
+ * Return the custom attribute info for attributes defined for the
+ * reflection handle @obj. The objects.
+ *
+ * On failure returns NULL and sets @error.
+ *
+ * FIXME this function leaks like a sieve for SRE objects.
+ */
+MonoCustomAttrInfo*
+mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
+{
+ MonoClass *klass;
+ MonoCustomAttrInfo *cinfo = NULL;
+
+ mono_error_init (error);
+
+ klass = obj->vtable->klass;
+ if (klass == mono_defaults.runtimetype_class) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, NULL);
+ klass = mono_class_from_mono_type (type);
+ /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
+ cinfo = mono_custom_attrs_from_class_checked (klass, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
+ MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
+ cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
+ MonoReflectionModule *module = (MonoReflectionModule*)obj;
+ cinfo = mono_custom_attrs_from_module (module->image, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("MonoProperty", klass->name) == 0) {
+ MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
+ cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("MonoEvent", klass->name) == 0) {
+ MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
+ cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("MonoField", klass->name) == 0) {
+ MonoReflectionField *rfield = (MonoReflectionField*)obj;
+ cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
+ return_val_if_nok (error, NULL);
+ } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
+ MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
+ cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
+ return_val_if_nok (error, NULL);
+ } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
+ MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
+ cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
+ return_val_if_nok (error, NULL);
+ } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
+ MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
+ MonoClass *member_class = mono_object_class (param->MemberImpl);
+ if (mono_class_is_reflection_method_or_constructor (member_class)) {
+ MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
+ cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
+ return_val_if_nok (error, NULL);
+ } else if (mono_is_sr_mono_property (member_class)) {
+ MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
+ MonoMethod *method;
+ if (!(method = prop->property->get))
+ method = prop->property->set;
+ g_assert (method);
+
+ cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
+ return_val_if_nok (error, NULL);
+ }
+#ifndef DISABLE_REFLECTION_EMIT
+ else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
+ MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
+ return_val_if_nok (error, NULL);
+ cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
+ return_val_if_nok (error, NULL);
+ } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
+ MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
+ MonoMethod *method = NULL;
+ if (mono_is_sre_ctor_builder (mono_object_class (c->cb)))
+ method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
+ else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb)))
+ method = ((MonoReflectionMethod *)c->cb)->method;
+ else
+ g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
+
+ cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
+ return_val_if_nok (error, NULL);
+ }
+#endif
+ else {
+ char *type_name = mono_type_get_full_name (member_class);
+ mono_error_set_not_supported (error,
+ "Custom attributes on a ParamInfo with member %s are not supported",
+ type_name);
+ g_free (type_name);
+ return NULL;
+ }
+ } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
+ MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
+ } else if (strcmp ("TypeBuilder", klass->name) == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
+ } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
+ MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
+ } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
+ MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
+ } else if (strcmp ("MethodBuilder", klass->name) == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
+ } else if (strcmp ("FieldBuilder", klass->name) == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
+ } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
+ MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
+ cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
+ return_val_if_nok (error, NULL);
+ } else { /* handle other types here... */
+ g_error ("get custom attrs not yet supported for %s", klass->name);
+ }
+
+ return cinfo;
+}
+
+/*
+ * mono_reflection_get_custom_attrs_by_type:
+ * @obj: a reflection object handle
+ *
+ * Return an array with all the custom attributes defined of the
+ * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
+ * of that type are returned. The objects are fully build. Return NULL if a loading error
+ * occurs.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
+{
+ MonoArray *result;
+ MonoCustomAttrInfo *cinfo;
+
+ mono_error_init (error);
+
+ cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
+ return_val_if_nok (error, NULL);
+ if (cinfo) {
+ result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
+ if (!cinfo->cached)
+ mono_custom_attrs_free (cinfo);
+ if (!result)
+ return NULL;
+ } else {
+ result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
+ }
+
+ return result;
+}
+
+/*
+ * mono_reflection_get_custom_attrs:
+ * @obj: a reflection object handle
+ *
+ * Return an array with all the custom attributes defined of the
+ * reflection handle @obj. The objects are fully build. Return NULL if a loading error
+ * occurs.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs (MonoObject *obj)
+{
+ MonoError error;
+
+ return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
+}
+
+/*
+ * mono_reflection_get_custom_attrs_data:
+ * @obj: a reflection obj handle
+ *
+ * Returns an array of System.Reflection.CustomAttributeData,
+ * which include information about attributes reflected on
+ * types loaded using the Reflection Only methods
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_data (MonoObject *obj)
+{
+ MonoError error;
+ MonoArray* result;
+ result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+/*
+ * mono_reflection_get_custom_attrs_data_checked:
+ * @obj: a reflection obj handle
+ * @error: set on error
+ *
+ * Returns an array of System.Reflection.CustomAttributeData,
+ * which include information about attributes reflected on
+ * types loaded using the Reflection Only methods
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
+{
+ MonoArray *result;
+ MonoCustomAttrInfo *cinfo;
+
+ mono_error_init (error);
+
+ cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
+ return_val_if_nok (error, NULL);
+ if (cinfo) {
+ result = mono_custom_attrs_data_construct (cinfo, error);
+ if (!cinfo->cached)
+ mono_custom_attrs_free (cinfo);
+ return_val_if_nok (error, NULL);
+ } else
+ result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
+
+ return result;
+}
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__ */
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
-#include <mono/utils/w32handle.h>
//#define DEBUG_DOMAIN_UNLOAD 1
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;
}
#ifndef HOST_WIN32
wapi_cleanup ();
- mono_w32handle_cleanup ();
#endif
}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__
+#define __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__
+
+#include <mono/metadata/object.h>
+#include <mono/metadata/metadata-internals.h>
+
+typedef struct {
+ guint32 import_lookup_table;
+ guint32 timestamp;
+ guint32 forwarder;
+ guint32 name_rva;
+ guint32 import_address_table_rva;
+} MonoIDT;
+
+typedef struct {
+ guint32 name_rva;
+ guint32 flags;
+} MonoILT;
+
+
+void
+mono_dynamic_images_init (void);
+
+void
+mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj);
+
+gboolean
+mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token);
+
+MonoDynamicImage*
+mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name);
+
+guint32
+mono_dynamic_image_add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2);
+
+void
+mono_dynimage_alloc_table (MonoDynamicTable *table, guint nrows);
+
+#endif /* __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__ */
+
--- /dev/null
+/*
+ * dynamic-image.c: Images created at runtime.
+ *
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "mono/metadata/object.h"
+#include "mono/metadata/dynamic-image-internals.h"
+#include "mono/metadata/dynamic-stream-internals.h"
+#include "mono/metadata/gc-internals.h"
+#include "mono/metadata/metadata-internals.h"
+#include "mono/metadata/profiler-private.h"
+#include "mono/metadata/reflection-internals.h"
+#include "mono/metadata/sre-internals.h"
+#include "mono/utils/checked-build.h"
+#include "mono/utils/mono-error-internals.h"
+#include "mono/utils/mono-os-mutex.h"
+
+const unsigned char table_sizes [MONO_TABLE_NUM] = {
+ MONO_MODULE_SIZE,
+ MONO_TYPEREF_SIZE,
+ MONO_TYPEDEF_SIZE,
+ 0,
+ MONO_FIELD_SIZE,
+ 0,
+ MONO_METHOD_SIZE,
+ 0,
+ MONO_PARAM_SIZE,
+ MONO_INTERFACEIMPL_SIZE,
+ MONO_MEMBERREF_SIZE, /* 0x0A */
+ MONO_CONSTANT_SIZE,
+ MONO_CUSTOM_ATTR_SIZE,
+ MONO_FIELD_MARSHAL_SIZE,
+ MONO_DECL_SECURITY_SIZE,
+ MONO_CLASS_LAYOUT_SIZE,
+ MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
+ MONO_STAND_ALONE_SIGNATURE_SIZE,
+ MONO_EVENT_MAP_SIZE,
+ 0,
+ MONO_EVENT_SIZE,
+ MONO_PROPERTY_MAP_SIZE,
+ 0,
+ MONO_PROPERTY_SIZE,
+ MONO_METHOD_SEMA_SIZE,
+ MONO_METHODIMPL_SIZE,
+ MONO_MODULEREF_SIZE, /* 0x1A */
+ MONO_TYPESPEC_SIZE,
+ MONO_IMPLMAP_SIZE,
+ MONO_FIELD_RVA_SIZE,
+ 0,
+ 0,
+ MONO_ASSEMBLY_SIZE, /* 0x20 */
+ MONO_ASSEMBLY_PROCESSOR_SIZE,
+ MONO_ASSEMBLYOS_SIZE,
+ MONO_ASSEMBLYREF_SIZE,
+ MONO_ASSEMBLYREFPROC_SIZE,
+ MONO_ASSEMBLYREFOS_SIZE,
+ MONO_FILE_SIZE,
+ MONO_EXP_TYPE_SIZE,
+ MONO_MANIFEST_SIZE,
+ MONO_NESTED_CLASS_SIZE,
+
+ MONO_GENERICPARAM_SIZE, /* 0x2A */
+ MONO_METHODSPEC_SIZE,
+ MONO_GENPARCONSTRAINT_SIZE
+
+};
+
+// The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
+static GPtrArray *dynamic_images;
+static mono_mutex_t dynamic_images_mutex;
+
+static inline void
+dynamic_images_lock (void)
+{
+ mono_os_mutex_lock (&dynamic_images_mutex);
+}
+
+static inline void
+dynamic_images_unlock (void)
+{
+ mono_os_mutex_unlock (&dynamic_images_mutex);
+}
+
+void
+mono_dynamic_images_init (void)
+{
+ mono_os_mutex_init (&dynamic_images_mutex);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static void
+string_heap_init (MonoDynamicStream *sh)
+{
+ mono_dynstream_init (sh);
+}
+#endif
+
+#ifndef DISABLE_REFLECTION_EMIT
+static int
+mono_blob_entry_hash (const char* str)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint len, h;
+ const char *end;
+ len = mono_metadata_decode_blob_size (str, &str);
+ if (len > 0) {
+ end = str + len;
+ h = *str;
+ for (str += 1; str < end; str++)
+ h = (h << 5) - h + *str;
+ return h;
+ } else {
+ return 0;
+ }
+}
+
+static gboolean
+mono_blob_entry_equal (const char *str1, const char *str2) {
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ int len, len2;
+ const char *end1;
+ const char *end2;
+ len = mono_metadata_decode_blob_size (str1, &end1);
+ len2 = mono_metadata_decode_blob_size (str2, &end2);
+ if (len != len2)
+ return 0;
+ return memcmp (end1, end2, len) == 0;
+}
+#endif
+
+
+/**
+ * mono_find_dynamic_image_owner:
+ *
+ * Find the dynamic image, if any, which a given pointer is located in the memory of.
+ */
+MonoImage *
+mono_find_dynamic_image_owner (void *ptr)
+{
+ MonoImage *owner = NULL;
+ int i;
+
+ dynamic_images_lock ();
+
+ if (dynamic_images)
+ {
+ for (i = 0; !owner && i < dynamic_images->len; ++i) {
+ MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
+ if (mono_mempool_contains_addr (image->mempool, ptr))
+ owner = image;
+ }
+ }
+
+ dynamic_images_unlock ();
+
+ return owner;
+}
+
+static inline void
+dynamic_image_lock (MonoDynamicImage *image)
+{
+ MONO_ENTER_GC_SAFE;
+ mono_image_lock ((MonoImage*)image);
+ MONO_EXIT_GC_SAFE;
+}
+
+static inline void
+dynamic_image_unlock (MonoDynamicImage *image)
+{
+ mono_image_unlock ((MonoImage*)image);
+}
+
+void
+mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ dynamic_image_lock (assembly);
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
+ dynamic_image_unlock (assembly);
+}
+
+static MonoObject*
+lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoObject *obj;
+
+ dynamic_image_lock (assembly);
+ obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+ dynamic_image_unlock (assembly);
+
+ return obj;
+}
+
+/**
+ *
+ * mono_dynamic_image_is_valid_token:
+ *
+ * Returns TRUE if token is valid in the given image.
+ *
+ */
+gboolean
+mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token)
+{
+ return lookup_dyn_token (image, token) != NULL;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+
+#endif /* DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+/**
+ * mono_reflection_lookup_dynamic_token:
+ *
+ * Finish the Builder object pointed to by TOKEN and return the corresponding
+ * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
+ * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
+ * mapping table.
+ *
+ * LOCKING: Take the loader lock
+ */
+gpointer
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+{
+ MonoDynamicImage *assembly = (MonoDynamicImage*)image;
+ MonoObject *obj;
+ MonoClass *klass;
+
+ mono_error_init (error);
+
+ obj = lookup_dyn_token (assembly, token);
+ if (!obj) {
+ if (valid_token)
+ g_error ("Could not find required dynamic token 0x%08x", token);
+ else {
+ mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
+ return NULL;
+ }
+ }
+
+ if (!handle_class)
+ handle_class = &klass;
+ gpointer result = mono_reflection_resolve_object (image, obj, handle_class, context, error);
+ return result;
+}
+
+/*
+ * mono_image_register_token:
+ *
+ * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
+ * the Module.ResolveXXXToken () methods to work.
+ */
+void
+mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
+{
+ MonoObject *prev;
+
+ dynamic_image_lock (assembly);
+ prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+ if (prev) {
+ /* There could be multiple MethodInfo objects with the same token */
+ //g_assert (prev == obj);
+ } else {
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
+ }
+ dynamic_image_unlock (assembly);
+}
+
+#else /* DISABLE_REFLECTION_EMIT */
+
+gpointer
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+{
+ mono_error_init (error);
+ return NULL;
+}
+
+void
+mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
+{
+}
+
+#endif /* DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+MonoDynamicImage*
+mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
+{
+ static const guchar entrycode [16] = {0xff, 0x25, 0};
+ MonoDynamicImage *image;
+ int i;
+
+ const char *version;
+
+ if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
+ version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
+ else
+ version = mono_get_runtime_info ()->runtime_version;
+
+#if HAVE_BOEHM_GC
+ /* The MonoGHashTable's need GC tracking */
+ image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
+#else
+ image = g_new0 (MonoDynamicImage, 1);
+#endif
+
+ mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
+
+ /*g_print ("created image %p\n", image);*/
+ /* keep in sync with image.c */
+ image->image.name = assembly_name;
+ image->image.assembly_name = image->image.name; /* they may be different */
+ image->image.module_name = module_name;
+ image->image.version = g_strdup (version);
+ image->image.md_version_major = 1;
+ image->image.md_version_minor = 1;
+ image->image.dynamic = TRUE;
+
+ image->image.references = g_new0 (MonoAssembly*, 1);
+ image->image.references [0] = NULL;
+
+ mono_image_init (&image->image);
+
+ image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
+ image->method_to_table_idx = g_hash_table_new (NULL, NULL);
+ image->field_to_table_idx = g_hash_table_new (NULL, NULL);
+ image->method_aux_hash = g_hash_table_new (NULL, NULL);
+ image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
+ image->handleref = g_hash_table_new (NULL, NULL);
+ image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
+ image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
+ image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
+ image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
+ image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
+ image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
+ image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
+ image->gen_params = g_ptr_array_new ();
+ image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
+
+ /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
+ string_heap_init (&image->sheap);
+ mono_dynstream_add_data (&image->us, "", 1);
+ mono_dynamic_image_add_to_blob_cached (image, (char*) "", 1, NULL, 0);
+ /* import tables... */
+ mono_dynstream_add_data (&image->code, (char*)entrycode, sizeof (entrycode));
+ image->iat_offset = mono_dynstream_add_zero (&image->code, 8); /* two IAT entries */
+ image->idt_offset = mono_dynstream_add_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
+ image->imp_names_offset = mono_dynstream_add_zero (&image->code, 2); /* flags for name entry */
+ mono_dynstream_add_data (&image->code, "_CorExeMain", 12);
+ mono_dynstream_add_data (&image->code, "mscoree.dll", 12);
+ image->ilt_offset = mono_dynstream_add_zero (&image->code, 8); /* two ILT entries */
+ mono_dynstream_data_align (&image->code);
+
+ image->cli_header_offset = mono_dynstream_add_zero (&image->code, sizeof (MonoCLIHeader));
+
+ for (i=0; i < MONO_TABLE_NUM; ++i) {
+ image->tables [i].next_idx = 1;
+ image->tables [i].columns = table_sizes [i];
+ }
+
+ image->image.assembly = (MonoAssembly*)assembly;
+ image->run = assembly->run;
+ image->save = assembly->save;
+ image->pe_kind = 0x1; /* ILOnly */
+ image->machine = 0x14c; /* I386 */
+
+ mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
+
+ dynamic_images_lock ();
+
+ if (!dynamic_images)
+ dynamic_images = g_ptr_array_new ();
+
+ g_ptr_array_add (dynamic_images, image);
+
+ dynamic_images_unlock ();
+
+ return image;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+MonoDynamicImage*
+mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+#endif /* DISABLE_REFLECTION_EMIT */
+
+guint32
+mono_dynamic_image_add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 idx;
+ char *copy;
+ gpointer oldkey, oldval;
+
+ copy = (char *)g_malloc (s1+s2);
+ memcpy (copy, b1, s1);
+ memcpy (copy + s1, b2, s2);
+ if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
+ g_free (copy);
+ idx = GPOINTER_TO_UINT (oldval);
+ } else {
+ idx = mono_dynstream_add_data (&assembly->blob, b1, s1);
+ mono_dynstream_add_data (&assembly->blob, b2, s2);
+ g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
+ }
+ return idx;
+}
+
+void
+mono_dynimage_alloc_table (MonoDynamicTable *table, guint nrows)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ table->rows = nrows;
+ g_assert (table->columns);
+ if (nrows + 1 >= table->alloc_rows) {
+ while (nrows + 1 >= table->alloc_rows) {
+ if (table->alloc_rows == 0)
+ table->alloc_rows = 16;
+ else
+ table->alloc_rows *= 2;
+ }
+
+ table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
+ }
+}
+
+
+static void
+free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
+{
+ g_free (key);
+}
+
+static void
+release_hashtable (MonoGHashTable **hash)
+{
+ if (*hash) {
+ mono_g_hash_table_destroy (*hash);
+ *hash = NULL;
+ }
+}
+
+void
+mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
+{
+ release_hashtable (&image->token_fixups);
+ release_hashtable (&image->handleref_managed);
+ release_hashtable (&image->tokens);
+ release_hashtable (&image->remapped_tokens);
+ release_hashtable (&image->generic_def_objects);
+ release_hashtable (&image->methodspec);
+}
+
+// Free dynamic image pass one: Free resources but not image itself
+void
+mono_dynamic_image_free (MonoDynamicImage *image)
+{
+ MonoDynamicImage *di = image;
+ GList *list;
+ int i;
+
+ if (di->methodspec)
+ mono_g_hash_table_destroy (di->methodspec);
+ if (di->typespec)
+ g_hash_table_destroy (di->typespec);
+ if (di->typeref)
+ g_hash_table_destroy (di->typeref);
+ if (di->handleref)
+ g_hash_table_destroy (di->handleref);
+ if (di->handleref_managed)
+ mono_g_hash_table_destroy (di->handleref_managed);
+ if (di->tokens)
+ mono_g_hash_table_destroy (di->tokens);
+ if (di->remapped_tokens)
+ mono_g_hash_table_destroy (di->remapped_tokens);
+ if (di->generic_def_objects)
+ mono_g_hash_table_destroy (di->generic_def_objects);
+ if (di->blob_cache) {
+ g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
+ g_hash_table_destroy (di->blob_cache);
+ }
+ if (di->standalonesig_cache)
+ g_hash_table_destroy (di->standalonesig_cache);
+ for (list = di->array_methods; list; list = list->next) {
+ ArrayMethod *am = (ArrayMethod *)list->data;
+ mono_sre_array_method_free (am);
+ }
+ g_list_free (di->array_methods);
+ if (di->gen_params) {
+ for (i = 0; i < di->gen_params->len; i++) {
+ GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
+ mono_sre_generic_param_table_entry_free (entry);
+ }
+ g_ptr_array_free (di->gen_params, TRUE);
+ }
+ if (di->token_fixups)
+ mono_g_hash_table_destroy (di->token_fixups);
+ if (di->method_to_table_idx)
+ g_hash_table_destroy (di->method_to_table_idx);
+ if (di->field_to_table_idx)
+ g_hash_table_destroy (di->field_to_table_idx);
+ if (di->method_aux_hash)
+ g_hash_table_destroy (di->method_aux_hash);
+ if (di->vararg_aux_hash)
+ g_hash_table_destroy (di->vararg_aux_hash);
+ g_free (di->strong_name);
+ g_free (di->win32_res);
+ if (di->public_key)
+ g_free (di->public_key);
+
+ /*g_print ("string heap destroy for image %p\n", di);*/
+ mono_dynamic_stream_reset (&di->sheap);
+ mono_dynamic_stream_reset (&di->code);
+ mono_dynamic_stream_reset (&di->resources);
+ mono_dynamic_stream_reset (&di->us);
+ mono_dynamic_stream_reset (&di->blob);
+ mono_dynamic_stream_reset (&di->tstream);
+ mono_dynamic_stream_reset (&di->guid);
+ for (i = 0; i < MONO_TABLE_NUM; ++i) {
+ g_free (di->tables [i].values);
+ }
+
+ dynamic_images_lock ();
+
+ if (dynamic_images)
+ g_ptr_array_remove (dynamic_images, di);
+
+ dynamic_images_unlock ();
+}
+
+// Free dynamic image pass two: Free image itself (might never get called in some debug modes)
+void
+mono_dynamic_image_free_image (MonoDynamicImage *image)
+{
+ /* See create_dynamic_mono_image () */
+#if HAVE_BOEHM_GC
+ /* Allocated using GC_MALLOC */
+#else
+ g_free (image);
+#endif
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__
+#define __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__
+
+#include <mono/metadata/object.h>
+#include <mono/metadata/metadata-internals.h>
+
+void
+mono_dynstream_init (MonoDynamicStream *stream);
+
+guint32
+mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str);
+
+guint32
+mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error);
+
+guint32
+mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len);
+
+guint32
+mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len);
+
+void
+mono_dynstream_data_align (MonoDynamicStream *stream);
+
+#endif /* __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__ */
+
--- /dev/null
+/*
+ * dynamic-stream.c: MonoDynamicStream
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/metadata/dynamic-stream-internals.h"
+#include "mono/metadata/metadata-internals.h"
+#include "mono/utils/checked-build.h"
+#include "mono/utils/mono-error-internals.h"
+
+void
+mono_dynstream_init (MonoDynamicStream *sh)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ sh->index = 0;
+ sh->alloc_size = 4096;
+ sh->data = (char *)g_malloc (4096);
+ sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ mono_dynstream_insert_string (sh, "");
+}
+
+static void
+make_room_in_stream (MonoDynamicStream *stream, int size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (size <= stream->alloc_size)
+ return;
+
+ while (stream->alloc_size <= size) {
+ if (stream->alloc_size < 4096)
+ stream->alloc_size = 4096;
+ else
+ stream->alloc_size *= 2;
+ }
+
+ stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
+}
+
+guint32
+mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 idx;
+ guint32 len;
+ gpointer oldkey, oldval;
+
+ if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
+ return GPOINTER_TO_UINT (oldval);
+
+ len = strlen (str) + 1;
+ idx = sh->index;
+
+ make_room_in_stream (sh, idx + len);
+
+ /*
+ * We strdup the string even if we already copy them in sh->data
+ * so that the string pointers in the hash remain valid even if
+ * we need to realloc sh->data. We may want to avoid that later.
+ */
+ g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
+ memcpy (sh->data + idx, str, len);
+ sh->index += len;
+ return idx;
+}
+
+guint32
+mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+ char *name = mono_string_to_utf8_checked (str, error);
+ return_val_if_nok (error, -1);
+ guint32 idx;
+ idx = mono_dynstream_insert_string (sh, name);
+ g_free (name);
+ return idx;
+}
+
+guint32
+mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 idx;
+
+ make_room_in_stream (stream, stream->index + len);
+ memcpy (stream->data + stream->index, data, len);
+ idx = stream->index;
+ stream->index += len;
+ /*
+ * align index? Not without adding an additional param that controls it since
+ * we may store a blob value in pieces.
+ */
+ return idx;
+}
+
+guint32
+mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 idx;
+
+ make_room_in_stream (stream, stream->index + len);
+ memset (stream->data + stream->index, 0, len);
+ idx = stream->index;
+ stream->index += len;
+ return idx;
+}
+
+void
+mono_dynstream_data_align (MonoDynamicStream *stream)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 count = stream->index % 4;
+
+ /* we assume the stream data will be aligned */
+ if (count)
+ mono_dynstream_add_zero (stream, 4 - count);
+}
+
ifh = g_new (IncrementalFind, 1);
ifh->find_handle = find_handle;
ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
- if (mono_error_set_pending_exception (&error))
+ if (mono_error_set_pending_exception (&error)) {
+ MONO_ENTER_GC_SAFE;
+ FindClose (find_handle);
+ MONO_EXIT_GC_SAFE;
+ g_free (ifh);
return NULL;
+ }
ifh->domain = mono_domain_get ();
*handle = ifh;
if (options & FileOptions_Temporary)
attributes |= FILE_ATTRIBUTE_TEMPORARY;
- /* Not sure if we should set FILE_FLAG_OVERLAPPED, how does this mix with the "Async" bool here? */
- if (options & FileOptions_Asynchronous)
- attributes |= FILE_FLAG_OVERLAPPED;
-
if (options & FileOptions_WriteThrough)
attributes |= FILE_FLAG_WRITE_THROUGH;
} else
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);
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);
finalize_domain_objects ();
+ 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 ();
/* Temporary place for some of the handle enabled wrapper functions*/
MonoStringHandle
-mono_string_new_handle (MonoDomain *domain, const char *data)
+mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error)
{
- return MONO_HANDLE_NEW (MonoString, mono_string_new (domain, data));
+ return MONO_HANDLE_NEW (MonoString, mono_string_new_checked (domain, data, error));
}
MonoArrayHandle
} while (0)
+#define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE))))
+
/* Baked typed handles we all want */
TYPED_HANDLE_DECL (MonoString);
TYPED_HANDLE_DECL (MonoArray);
//FIXME this should go somewhere else
-MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data);
+MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
G_END_DECLS
ICALL (COMPO_W_1, "W32ErrorMessage", ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage)
ICALL_TYPE(DEFAULTC, "System.Configuration.DefaultConfig", DEFAULTC_1)
-ICALL(DEFAULTC_1, "get_bundled_machine_config", get_bundled_machine_config)
+HANDLES(ICALL(DEFAULTC_1, "get_bundled_machine_config", get_bundled_machine_config))
ICALL(DEFAULTC_2, "get_machine_config_path", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path)
/* Note that the below icall shares the same function as DefaultConfig uses */
ICALL(ENV_15, "get_TickCount", ves_icall_System_Environment_get_TickCount)
ICALL(ENV_16, "get_UserName", ves_icall_System_Environment_get_UserName)
ICALL(ENV_16m, "internalBroadcastSettingChange", ves_icall_System_Environment_BroadcastSettingChange)
-ICALL(ENV_17, "internalGetEnvironmentVariable", ves_icall_System_Environment_GetEnvironmentVariable)
-ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath)
-ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome)
+HANDLES(ICALL(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Environment_GetEnvironmentVariable_native))
+HANDLES(ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath))
+HANDLES(ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome))
ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set)
ICALL_TYPE(GC, "System.GC", GC_0)
ICALL(MONOIO_33, "get_VolumeSeparatorChar", ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar)
ICALL_TYPE(IOPATH, "System.IO.Path", IOPATH_1)
-ICALL(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path)
+HANDLES(ICALL(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path))
ICALL_TYPE(IOSELECTOR, "System.IOSelector", IOSELECTOR_1)
ICALL(IOSELECTOR_1, "Add", ves_icall_System_IOSelector_Add)
ICALL(OBJ_3, "MemberwiseClone", ves_icall_System_Object_MemberwiseClone)
ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1a)
-ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId)
+HANDLES(ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId))
ICALL(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly)
ICALL(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly)
ICALL(ASSEM_4, "GetExecutingAssembly", ves_icall_System_Reflection_Assembly_GetExecutingAssembly)
ICALL(ASSEM_13, "GetTypes", ves_icall_System_Reflection_Assembly_GetTypes)
ICALL(ASSEM_14, "InternalGetAssemblyName", ves_icall_System_Reflection_Assembly_InternalGetAssemblyName)
ICALL(ASSEM_15, "InternalGetType", ves_icall_System_Reflection_Assembly_InternalGetType)
-ICALL(ASSEM_16, "InternalImageRuntimeVersion", ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion)
+HANDLES(ICALL(ASSEM_16, "InternalImageRuntimeVersion", ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion))
ICALL(ASSEM_17, "LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom)
ICALL(ASSEM_18, "LoadPermissions", ves_icall_System_Reflection_Assembly_LoadPermissions)
ICALL(ASSEM_22, "get_code_base", ves_icall_System_Reflection_Assembly_get_code_base)
ICALL(ASSEM_23, "get_fullname", ves_icall_System_Reflection_Assembly_get_fullName)
ICALL(ASSEM_24, "get_global_assembly_cache", ves_icall_System_Reflection_Assembly_get_global_assembly_cache)
-ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location)
+HANDLES(ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location))
ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_load_with_partial_name)
ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0)
ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1)
ICALL(CATTR_DATA_1, "ResolveArgumentsInternal", ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal)
-ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_1)
-ICALL(ASSEMB_1, "InternalAddModule", ves_icall_AssemblyBuilder_InternalAddModule)
+ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_2)
ICALL(ASSEMB_2, "basic_init", ves_icall_AssemblyBuilder_basic_init)
#ifndef DISABLE_REFLECTION_EMIT
ICALL_TYPE(TYPEB, "System.Reflection.Emit.TypeBuilder", TYPEB_1)
ICALL(TYPEB_1, "create_generic_class", ves_icall_TypeBuilder_create_generic_class)
-ICALL(TYPEB_2, "create_internal_class", ves_icall_TypeBuilder_create_internal_class)
ICALL(TYPEB_3, "create_runtime_class", ves_icall_TypeBuilder_create_runtime_class)
ICALL(TYPEB_4, "get_IsGenericParameter", ves_icall_TypeBuilder_get_IsGenericParameter)
ICALL(TYPEB_5, "get_event_info", ves_icall_TypeBuilder_get_event_info)
-ICALL(TYPEB_6, "setup_generic_class", ves_icall_TypeBuilder_setup_generic_class)
ICALL(TYPEB_7, "setup_internal_class", ves_icall_TypeBuilder_setup_internal_class)
ICALL_TYPE(EVENTI, "System.Reflection.EventInfo", EVENTI_1)
ICALL_TYPE(MODULE, "System.Reflection.Module", MODULE_1)
ICALL(MODULE_1, "Close", ves_icall_System_Reflection_Module_Close)
ICALL(MODULE_2, "GetGlobalType", ves_icall_System_Reflection_Module_GetGlobalType)
-ICALL(MODULE_3, "GetGuidInternal", ves_icall_System_Reflection_Module_GetGuidInternal)
+HANDLES(ICALL(MODULE_3, "GetGuidInternal", ves_icall_System_Reflection_Module_GetGuidInternal))
ICALL(MODULE_14, "GetHINSTANCE", ves_icall_System_Reflection_Module_GetHINSTANCE)
ICALL(MODULE_4, "GetMDStreamVersion", ves_icall_System_Reflection_Module_GetMDStreamVersion)
ICALL(MODULE_5, "GetPEKind", ves_icall_System_Reflection_Module_GetPEKind)
HANDLES(ICALL(RT_19, "getFullName", ves_icall_System_RuntimeType_getFullName))
ICALL(RT_21, "get_DeclaringMethod", ves_icall_RuntimeType_get_DeclaringMethod)
ICALL(RT_22, "get_DeclaringType", ves_icall_RuntimeType_get_DeclaringType)
-ICALL(RT_23, "get_Name", ves_icall_RuntimeType_get_Name)
-ICALL(RT_24, "get_Namespace", ves_icall_RuntimeType_get_Namespace)
+HANDLES(ICALL(RT_23, "get_Name", ves_icall_RuntimeType_get_Name))
+HANDLES(ICALL(RT_24, "get_Namespace", ves_icall_RuntimeType_get_Namespace))
ICALL(RT_25, "get_core_clr_security_level", vell_icall_RuntimeType_get_core_clr_security_level)
ICALL(RT_26, "make_array_type", ves_icall_RuntimeType_make_array_type)
ICALL(RT_27, "make_byref_type", ves_icall_RuntimeType_make_byref_type)
ICALL_TYPE(NATIVEC, "System.Threading.NativeEventCalls", NATIVEC_1)
ICALL(NATIVEC_1, "CloseEvent_internal", ves_icall_System_Threading_Events_CloseEvent_internal)
-ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,bool&)", ves_icall_System_Threading_Events_CreateEvent_internal)
-ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,System.IO.MonoIOError&)", ves_icall_System_Threading_Events_OpenEvent_internal)
+ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal)
+ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,int&)", ves_icall_System_Threading_Events_OpenEvent_internal)
ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal)
ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal)
ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
-TYPED_HANDLE_DECL (MonoReflectionType);
-
/* Lazy class loading functions */
static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
return ret;
}
-ICALL_EXPORT MonoString*
-ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
+ICALL_EXPORT MonoStringHandle
+ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
{
- MonoDomain *domain = mono_domain_get ();
- MonoClass *klass = mono_class_from_mono_type (type->type);
+ MonoDomain *domain = mono_domain_get ();
+ MonoType *type = MONO_HANDLE_RAW(reftype)->type;
+ MonoClass *klass = mono_class_from_mono_type (type);
- if (type->type->byref) {
+ if (type->byref) {
char *n = g_strdup_printf ("%s&", klass->name);
- MonoString *res = mono_string_new (domain, n);
+ MonoStringHandle res = mono_string_new_handle (domain, n, error);
g_free (n);
return res;
} else {
- return mono_string_new (domain, klass->name);
+ return mono_string_new_handle (domain, klass->name, error);
}
}
-ICALL_EXPORT MonoString*
-ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
+ICALL_EXPORT MonoStringHandle
+ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
{
MonoDomain *domain = mono_domain_get ();
- MonoClass *klass = mono_class_from_mono_type (type->type);
+ MonoClass *klass = mono_class_from_mono_type_handle (type);
while (klass->nested_in)
klass = klass->nested_in;
if (klass->name_space [0] == '\0')
- return NULL;
+ return NULL_HANDLE_STRING;
else
- return mono_string_new (domain, klass->name_space);
+ return mono_string_new_handle (domain, klass->name_space, error);
}
ICALL_EXPORT gint32
return result;
}
-ICALL_EXPORT MonoString *
-ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
{
- MonoDomain *domain = mono_object_domain (assembly);
- MonoString *res;
-
- res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
-
- return res;
+ MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
+ MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
+ return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
}
ICALL_EXPORT MonoBoolean
return assembly->assembly->ref_only;
}
-ICALL_EXPORT MonoString *
-ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
{
- MonoDomain *domain = mono_object_domain (assembly);
+ MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
+ MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
- return mono_string_new (domain, assembly->assembly->image->version);
+ return mono_string_new_handle (domain, assembly->image->version, error);
}
ICALL_EXPORT MonoReflectionMethod*
return result;
}
-ICALL_EXPORT MonoString*
-ves_icall_System_Reflection_Assembly_GetAotId ()
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
{
int i;
guint8 aotid_sum = 0;
if (aotid_sum == 0)
return NULL;
-
- return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
+
+ gchar *guid = mono_guid_to_string((guint8*) aotid);
+ MonoStringHandle res = mono_string_new_handle (domain, guid, error);
+ g_free (guid);
+ return res;
}
static MonoObject*
return NULL_HANDLE_STRING;
}
- res = mono_string_new_handle (domain, name);
+ res = mono_string_new_handle (domain, name, error);
g_free (name);
return res;
mono_image_close (module->image);*/
}
-ICALL_EXPORT MonoString*
-ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
{
- MonoDomain *domain = mono_object_domain (module);
+ MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
+ MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
- g_assert (module->image);
- return mono_string_new (domain, module->image->guid);
+ g_assert (image);
+ return mono_string_new_handle (domain, image->guid, error);
}
ICALL_EXPORT gpointer
MonoObject *delegate;
gpointer func;
MonoMethod *method = info->method;
+ MonoMethodSignature *sig = mono_method_signature(method);
mono_class_init_checked (delegate_class, &error);
if (mono_error_set_pending_exception (&error))
}
}
+ if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
+ if (!method->is_inflated) {
+ mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
+ return NULL;
+ }
+ }
+
delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
if (mono_error_set_pending_exception (&error))
return NULL;
#endif
}
-ICALL_EXPORT MonoString *
-ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
{
- MonoError error;
const gchar *value;
- gchar *utf8_name;
- if (name == NULL)
- return NULL;
+ if (utf8_name == NULL)
+ return NULL_HANDLE_STRING;
- utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
- if (mono_error_set_pending_exception (&error))
- return NULL;
value = g_getenv (utf8_name);
- g_free (utf8_name);
-
if (value == 0)
- return NULL;
+ return NULL_HANDLE_STRING;
- return mono_string_new (mono_domain_get (), value);
+ return mono_string_new_handle (mono_domain_get (), value, error);
}
/*
exit (result);
}
-ICALL_EXPORT MonoString*
-ves_icall_System_Environment_GetGacPath (void)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Environment_GetGacPath (MonoError *error)
{
- return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
+ return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
}
ICALL_EXPORT MonoString*
return result;
}
-ICALL_EXPORT MonoString *
-ves_icall_System_Environment_InternalGetHome (void)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_Environment_InternalGetHome (MonoError *error)
{
- return mono_string_new (mono_domain_get (), g_get_home_dir ());
+ return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
}
static const char *encodings [] = {
}
}
-ICALL_EXPORT MonoString *
-ves_icall_System_IO_get_temp_path (void)
+ICALL_EXPORT MonoStringHandle
+ves_icall_System_IO_get_temp_path (MonoError *error)
{
- return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
+ return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
}
#ifndef PLATFORM_NO_DRIVEINFO
return mono_string_new (mono_domain_get (), app_config);
}
-static MonoString *
-get_bundled_machine_config (void)
+/* this is an icall */
+static MonoStringHandle
+get_bundled_machine_config (MonoError *error)
{
const gchar *machine_config;
machine_config = mono_get_machine_config ();
if (!machine_config)
- return NULL;
+ return NULL_HANDLE_STRING;
- return mono_string_new (mono_domain_get (), machine_config);
+ return mono_string_new_handle (mono_domain_get (), machine_config, error);
}
ICALL_EXPORT MonoString *
ICALL_EXPORT gint32
ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
{
+#ifdef HOST_WIN32
return WaitForInputIdle (handle, milliseconds);
+#else
+ /*TODO: Not implemented*/
+ return WAIT_TIMEOUT;
+#endif
}
ICALL_EXPORT MonoBoolean
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)
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;
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)
/* 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);
#include "lock-tracer.h"
-
/*
* This is a very simple lock trace implementation. It can be used to verify that the runtime is
* correctly following all locking rules.
{
add_record (RECORD_LOCK_RELEASED, kind, lock);
}
-
-#endif
+#else
+ #ifdef _MSC_VER
+ // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+ void __mono_win32_lock_tracer_quiet_lnk4221(void) {}
+ #endif
+#endif /* LOCK_TRACER */
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
static void
mono_struct_delete_old (MonoClass *klass, char *ptr);
}
}
+static int offset_of_first_nonstatic_field(MonoClass *klass)
+{
+ int i;
+ for (i = 0; i < klass->field.count; i++) {
+ if (!(klass->fields[i].type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (&klass->fields[i]))
+ return klass->fields[i].offset - sizeof (MonoObject);
+ }
+
+ return 0;
+}
+
static void
emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
- MonoMarshalNative string_encoding)
+ int offset_of_first_child_field, MonoMarshalNative string_encoding)
{
MonoMarshalType *info;
int i;
if (klass->parent)
- emit_struct_conv(mb, klass->parent, to_object);
+ emit_struct_conv_full (mb, klass->parent, to_object, offset_of_first_nonstatic_field (klass), string_encoding);
info = mono_marshal_load_type_info (klass);
return;
if (klass->blittable) {
- int msize = mono_class_value_size (klass, NULL);
- g_assert (msize == info->native_size);
+ int usize = mono_class_value_size (klass, NULL);
+ g_assert (usize == info->native_size);
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, msize);
+ mono_mb_emit_icon (mb, usize);
mono_mb_emit_byte (mb, CEE_PREFIX1);
mono_mb_emit_byte (mb, CEE_CPBLK);
- mono_mb_emit_add_to_local (mb, 0, msize);
- mono_mb_emit_add_to_local (mb, 1, msize);
+ if (to_object) {
+ mono_mb_emit_add_to_local (mb, 0, usize);
+ mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
+ } else {
+ mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
+ mono_mb_emit_add_to_local (mb, 1, usize);
+ }
return;
}
static void
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
{
- emit_struct_conv_full (mb, klass, to_object, (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
}
static void
gboolean closed_over_null = FALSE;
MonoGenericContext *ctx = NULL;
MonoGenericContainer *container = NULL;
- MonoMethod *orig_method = NULL;
+ MonoMethod *orig_method = method;
WrapperInfo *info;
WrapperSubtype subtype = WRAPPER_SUBTYPE_NONE;
gboolean found;
* For generic delegates, create a generic wrapper, and return an instance to help AOT.
*/
if (method->is_inflated && subtype == WRAPPER_SUBTYPE_NONE) {
- orig_method = method;
ctx = &((MonoMethodInflated*)method)->context;
method = ((MonoMethodInflated*)method)->declaring;
#endif /* DISABLE_JIT */
info = mono_wrapper_info_create (mb, subtype);
- info->d.delegate_invoke.method = method;
+ info->d.delegate_invoke.method = orig_method;
if (ctx) {
MonoMethod *def;
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
mono_mb_emit_add_to_local (mb, index_var, 1);
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
if (need_free) {
if (!tres)
return tres;
- len = strlen (tres) + 1;
+ /*
+ * mono_string_to_utf8_checked() returns a memory area at least as large as the size of the
+ * MonoString, even if it contains NULL characters. The copy we allocate here has to be equally
+ * large.
+ */
+ len = MAX (strlen (tres) + 1, string->length);
ret = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (len);
memcpy (ret, tres, len);
g_free (tres);
free_generic_class (MonoGenericClass *gclass)
{
/* The gclass itself is allocated from the image set mempool */
- if (gclass->is_dynamic)
- mono_reflection_free_dynamic_generic_class (gclass);
if (gclass->cached_class && gclass->cached_class->interface_id)
mono_unload_interface_id (gclass->cached_class);
}
return gclass;
}
- if (is_dynamic) {
- MonoDynamicGenericClass *dgclass = mono_image_set_new0 (set, MonoDynamicGenericClass, 1);
- gclass = &dgclass->generic_class;
+ gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
+ if (is_dynamic)
gclass->is_dynamic = 1;
- } else {
- gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
- }
gclass->is_tb_open = is_tb_open;
gclass->container_class = container_class;
!mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
}
+mono_bool
+mono_type_is_generic_parameter (MonoType *type)
+{
+ return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
+}
+
/**
* mono_signature_get_return_type:
* @sig: the method signature inspected
typedef struct _MonoType MonoType;
typedef struct _MonoGenericInst MonoGenericInst;
typedef struct _MonoGenericClass MonoGenericClass;
-typedef struct _MonoDynamicGenericClass MonoDynamicGenericClass;
typedef struct _MonoGenericContext MonoGenericContext;
typedef struct _MonoGenericContainer MonoGenericContainer;
typedef struct _MonoGenericParam MonoGenericParam;
MONO_API mono_bool mono_type_is_void (MonoType *type);
MONO_API mono_bool mono_type_is_pointer (MonoType *type);
MONO_API mono_bool mono_type_is_reference (MonoType *type);
+mono_bool mono_type_is_generic_parameter (MonoType *type);
MONO_API MonoType*
mono_signature_get_return_type (MonoMethodSignature *sig);
if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
LOCK_DEBUG (g_message ("%s: (%d) interrupted waiting, returning -1", __func__, id));
return -1;
- } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
+ } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
LOCK_DEBUG (g_message ("%s: (%d) timed out waiting, returning FALSE", __func__, id));
return 0;
} else {
#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,
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);
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);
#include <mach/message.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
+#include <sys/sysctl.h>
#endif
-#if defined (__NetBSD__) || defined (__APPLE__)
+#if defined (__NetBSD__)
+#include <sys/param.h>
#include <sys/sysctl.h>
+#include <sys/vmmeter.h>
#endif
#include "metadata/mono-perfcounters.h"
#include "metadata/appdomain.h"
int mib[2] = {
CTL_HW,
#ifdef __NetBSD__
- HW_PHYSMEM
+ HW_PHYSMEM64
#else
HW_MEMSIZE
#endif
#elif defined (__NetBSD__)
struct vmtotal vm_total;
guint64 page_size;
- int mib [2];
+ int mib[2];
size_t len;
+ mib[0] = CTL_VM;
+ mib[1] = VM_METER;
- mib = {
- CTL_VM,
-#if defined (VM_METER)
- VM_METER
-#else
- VM_TOTAL
-#endif
- };
len = sizeof (vm_total);
sysctl (mib, 2, &vm_total, &len, NULL, 0);
- mib = {
- CTL_HW,
- HW_PAGESIZE
- };
+ mib[0] = CTL_HW;
+ mib[1] = HW_PAGESIZE;
+
len = sizeof (page_size);
- sysctl (mib, 2, &page_size, &len, NULL, 0
+ sysctl (mib, 2, &page_size, &len, NULL, 0);
- return ((guint64) value.t_free * page_size) / 1024;
+ return ((guint64) vm_total.t_free * page_size) / 1024;
#elif defined (__APPLE__)
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
mach_port_t host = mach_host_self();
*/
/* thread may be impersonating somebody */
- if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, 1, &token) == 0) {
+ if (OpenThreadToken (GetCurrentThread (), MAXIMUM_ALLOWED, 1, &token) == 0) {
/* if not take the process identity */
- OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token);
+ OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &token);
}
#else
token = GINT_TO_POINTER (geteuid ());
{
gboolean success = FALSE;
PACL pDACL = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
PSID pEveryoneSid = NULL;
- DWORD dwRes = GetNamedSecurityInfoW (path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, NULL);
+ DWORD dwRes = GetNamedSecurityInfoW (path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &pSD);
if (dwRes != ERROR_SUCCESS)
return FALSE;
/* Note: we don't need to check our own access -
we'll know soon enough when reading the file */
- if (pDACL)
- LocalFree (pDACL);
+ if (pSD)
+ LocalFree (pSD);
return success;
}
{
return TRUE;
}
-
-#endif
+#else
+ #ifdef _MSC_VER
+ // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+ void __mono_win32_null_gc_quiet_lnk4221(void) {}
+ #endif
+#endif /* HAVE_NULL_GC */
#include <mono/metadata/mempool.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/threads-types.h>
+#include <mono/metadata/handle.h>
#include <mono/io-layer/io-layer.h>
#include "mono/utils/mono-compiler.h"
#include "mono/utils/mono-error.h"
MonoType *type;
};
+/* Safely access System.Type from native code */
+TYPED_HANDLE_DECL (MonoReflectionType);
+
/* This corresponds to System.RuntimeType */
typedef struct {
MonoReflectionType type;
MonoException *abort_exc;
int abort_state_handle;
guint64 tid; /* This is accessed as a gsize in the code (so it can hold a 64bit pointer on systems that need it), but needs to reserve 64 bits of space on all machines as it corresponds to a field in managed code */
- HANDLE start_notify;
gpointer stack_ptr;
gpointer *static_data;
void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */
gpointer interrupt_on_stop;
gsize flags;
gpointer thread_pinning_ref;
+ gsize abort_protected_block_count;
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to this structure.
* Please synchronize any changes with InternalThread in Thread.cs, i.e. add the
* same field there.
*/
- gpointer unused1;
- gpointer unused2;
+ gsize unused1;
+ gsize unused2;
};
struct _MonoThread {
void (*mono_raise_exception_with_ctx) (MonoException *ex, MonoContext *ctx);
gboolean (*mono_exception_walk_trace) (MonoException *ex, MonoInternalExceptionFrameWalk func, gpointer user_data);
gboolean (*mono_install_handler_block_guard) (MonoThreadUnwindState *unwind_state);
+ gboolean (*mono_current_thread_has_handle_block_guard) (void);
} MonoRuntimeExceptionHandlingCallbacks;
/* used to free a dynamic method */
MonoString *name;
};
+/* Safely access System.Reflection.Assembly from native code */
+TYPED_HANDLE_DECL (MonoReflectionAssembly);
+
typedef struct {
MonoReflectionType *utype;
MonoArray *values;
guint32 token;
};
+/* Safely access System.Reflection.Module from native code */
+TYPED_HANDLE_DECL (MonoReflectionModule);
+
typedef struct {
MonoReflectionModule module;
MonoDynamicImage *dynamic_image;
} CattrNamedArg;
gboolean mono_image_create_pefile (MonoReflectionModuleBuilder *module, HANDLE file, MonoError *error);
-MonoReflectionModule * mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *assembly, MonoString *file_name, MonoError *error);
guint32 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str);
guint32 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec, gboolean register_token, MonoError *error);
guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error);
void mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb);
-void
-ves_icall_TypeBuilder_create_internal_class (MonoReflectionTypeBuilder *tb);
-
-void
-ves_icall_TypeBuilder_setup_generic_class (MonoReflectionTypeBuilder *tb);
-
MonoReflectionType*
ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb);
gboolean
mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error);
-gboolean
-mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token);
-
void
ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *method, MonoReflectionAssembly *assembly, gpointer data, guint32 data_length, MonoArray **ctor_args, MonoArray ** named_args);
MonoType*
mono_reflection_type_get_handle (MonoReflectionType *ref, MonoError *error);
-void
-mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass);
-
gboolean
mono_image_build_metadata (MonoReflectionModuleBuilder *module, MonoError *error);
MonoNativeThreadId tid;
int do_initialization = 0;
MonoDomain *last_domain = NULL;
+ MonoException * pending_tae = NULL;
mono_error_init (error);
if (do_initialization) {
MonoException *exc = NULL;
+
+ mono_threads_begin_abort_protected_block ();
mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
- if (exc != NULL && mono_error_ok (error)) {
- mono_error_set_exception_instance (error, exc);
- }
+ mono_threads_end_abort_protected_block ();
+
+ //exception extracted, error will be set to the right value later
+ if (exc == NULL && !mono_error_ok (error))//invoking failed but exc was not set
+ exc = mono_error_convert_to_exception (error);
+ else
+ mono_error_cleanup (error);
+
+ mono_error_init (error);
/* If the initialization failed, mark the class as unusable. */
/* Avoid infinite loops */
- if (!(mono_error_ok(error) ||
+ if (!(!exc ||
(klass->image == mono_defaults.corlib &&
!strcmp (klass->name_space, "System") &&
!strcmp (klass->name, "TypeInitializationException")))) {
MonoException *exc_to_throw = mono_get_exception_type_initialization_checked (full_name, exc, error);
g_free (full_name);
- return_val_if_nok (error, FALSE);
- mono_error_set_exception_instance (error, exc_to_throw);
+ mono_error_assert_ok (error); //We can't recover from this, no way to fail a type we can't alloc a failure.
- MonoException *exc_to_store = mono_error_convert_to_exception (error);
- /* What we really want to do here is clone the error object and store one copy in the
- * domain's exception hash and use the other one to error out here. */
- mono_error_init (error);
- mono_error_set_exception_instance (error, exc_to_store);
/*
* Store the exception object so it could be thrown on subsequent
* accesses.
mono_domain_lock (domain);
if (!domain->type_init_exception_hash)
domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "type initialization exceptions table");
- mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_store);
+ mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
mono_domain_unlock (domain);
}
mono_domain_set (last_domain, TRUE);
lock->done = TRUE;
mono_type_init_unlock (lock);
+ if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class)
+ pending_tae = exc;
+ //TAEs are blocked around .cctors, they must escape as soon as no cctor is left to run.
+ if (!pending_tae)
+ pending_tae = mono_thread_try_resume_interruption ();
} else {
/* this just blocks until the initializing thread is done */
mono_type_init_lock (lock);
vtable->initialized = 1;
mono_type_initialization_unlock ();
- if (vtable->init_failed) {
+ //TAE wins over TIE
+ if (pending_tae)
+ mono_error_set_exception_instance (error, pending_tae);
+ else if (vtable->init_failed) {
/* Either we were the initializing thread or we waited for the initialization */
mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
return FALSE;
if (!current_appdomain_delegate && !root_appdomain_delegate) {
mono_print_unhandled_exception (exc);
} else {
+ /* unhandled exception callbacks must not be aborted */
+ mono_threads_begin_abort_protected_block ();
if (root_appdomain_delegate)
call_unhandled_exception_delegate (root_domain, root_appdomain_delegate, exc);
if (current_appdomain_delegate)
call_unhandled_exception_delegate (current_domain, current_appdomain_delegate, exc);
+ mono_threads_end_abort_protected_block ();
}
/* set exitcode only if we will abort the process */
ac->msg->exc = NULL;
- MonoError invoke_error;
- res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args, &invoke_error);
+ res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args, &error);
+
+ /* The exit side of the invoke must not be aborted as it would leave the runtime in an undefined state */
+ mono_threads_begin_abort_protected_block ();
if (!ac->msg->exc) {
- MonoException *ex = mono_error_convert_to_exception (&invoke_error);
+ MonoException *ex = mono_error_convert_to_exception (&error);
ac->msg->exc = (MonoObject *)ex;
} else {
- mono_error_cleanup (&invoke_error);
+ mono_error_cleanup (&error);
}
MONO_OBJECT_SETREF (ac, res, res);
if (wait_event != NULL)
SetEvent (wait_event);
- if (ac->cb_method) {
+ mono_error_init (&error); //the else branch would leave it in an undefined state
+ if (ac->cb_method)
mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- }
+
+ mono_threads_end_abort_protected_block ();
+
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
}
return res;
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);
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;
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)
{
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 {
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,
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 */
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);
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);
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_REFLECTION_CACHE_H__
+#define __MONO_METADATA_REFLECTION_CACHE_H__
+
+#include <glib.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/mono-hash.h>
+#include <mono/metadata/mempool.h>
+
+/*
+ * We need to return always the same object for MethodInfo, FieldInfo etc..
+ * but we need to consider the reflected type.
+ * type uses a different hash, since it uses custom hash/equal functions.
+ */
+
+typedef struct {
+ gpointer item;
+ MonoClass *refclass;
+} ReflectedEntry;
+
+gboolean
+reflected_equal (gconstpointer a, gconstpointer b);
+
+guint
+reflected_hash (gconstpointer a);
+
+#ifdef HAVE_BOEHM_GC
+/* ReflectedEntry doesn't need to be GC tracked */
+#define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
+#define FREE_REFENTRY(entry) g_free ((entry))
+#define REFENTRY_REQUIRES_CLEANUP
+#else
+#define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
+/* FIXME: */
+#define FREE_REFENTRY(entry)
+#endif
+
+
+#define CACHE_OBJECT(t,p,o,k) \
+ do { \
+ t _obj; \
+ ReflectedEntry pe; \
+ pe.item = (p); \
+ pe.refclass = (k); \
+ mono_domain_lock (domain); \
+ if (!domain->refobject_hash) \
+ domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
+ _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
+ if (!_obj) { \
+ ReflectedEntry *e = ALLOC_REFENTRY; \
+ e->item = (p); \
+ e->refclass = (k); \
+ mono_g_hash_table_insert (domain->refobject_hash, e,o); \
+ _obj = o; \
+ } \
+ mono_domain_unlock (domain); \
+ return _obj; \
+ } while (0)
+
+#define CHECK_OBJECT(t,p,k) \
+ do { \
+ t _obj; \
+ ReflectedEntry e; \
+ e.item = (p); \
+ e.refclass = (k); \
+ mono_domain_lock (domain); \
+ if (!domain->refobject_hash) \
+ domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
+ if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
+ mono_domain_unlock (domain); \
+ return _obj; \
+ } \
+ mono_domain_unlock (domain); \
+ } while (0)
+
+
+#endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/
/*
* Copyright 2014 Xamarin Inc
+ * Copyright 2016 Microsoft
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#ifndef __MONO_METADATA_REFLECTION_INTERNALS_H__
#define __MONO_METADATA_REFLECTION_INTERNALS_H__
+#include <mono/metadata/object-internals.h>
#include <mono/metadata/reflection.h>
+#include <mono/metadata/class-internals.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-error.h>
+gboolean
+mono_reflection_is_usertype (MonoReflectionType *ref);
+
+MonoReflectionType*
+mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
+
MonoType*
mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, mono_bool ignorecase, mono_bool *type_resolve, MonoError *error);
MonoReflectionMethodBody*
mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error);
+MonoClass *
+mono_class_from_mono_type_handle (MonoReflectionTypeHandle h);
+
#endif /* __MONO_METADATA_REFLECTION_INTERNALS_H__ */
/*
- * reflection.c: Routines for creating an image at runtime.
+ * reflection.c: System.Type icalls and related reflection queries.
*
* Author:
* Paolo Molaro (lupus@ximian.com)
* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
*
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
-#include "mono/utils/mono-digest.h"
#include "mono/utils/mono-membar.h"
#include "mono/metadata/reflection-internals.h"
#include "mono/metadata/tabledefs.h"
#include <mono/metadata/profiler-private.h>
#include "mono/metadata/class-internals.h"
#include "mono/metadata/gc-internals.h"
-#include "mono/metadata/tokentype.h"
#include "mono/metadata/domain-internals.h"
#include "mono/metadata/opcodes.h"
#include "mono/metadata/assembly.h"
#include <mono/metadata/exception.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/security-manager.h>
+#include <mono/metadata/reflection-cache.h>
+#include <mono/metadata/sre-internals.h>
#include <stdio.h>
#include <glib.h>
#include <errno.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/checked-build.h>
-static gboolean is_usertype (MonoReflectionType *ref);
-static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
-static gboolean mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error);
-static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
-
-typedef struct {
- char *p;
- char *buf;
- char *end;
-} SigBuffer;
-
-#define TEXT_OFFSET 512
-#define CLI_H_SIZE 136
-#define FILE_ALIGN 512
-#define VIRT_ALIGN 8192
-#define START_TEXT_RVA 0x00002000
-
-typedef struct {
- MonoReflectionILGen *ilgen;
- MonoReflectionType *rtype;
- MonoArray *parameters;
- MonoArray *generic_params;
- MonoGenericContainer *generic_container;
- MonoArray *pinfo;
- MonoArray *opt_types;
- guint32 attrs;
- guint32 iattrs;
- guint32 call_conv;
- guint32 *table_idx; /* note: it's a pointer */
- MonoArray *code;
- MonoObject *type;
- MonoString *name;
- MonoBoolean init_locals;
- MonoBoolean skip_visibility;
- MonoArray *return_modreq;
- MonoArray *return_modopt;
- MonoArray *param_modreq;
- MonoArray *param_modopt;
- MonoArray *permissions;
- MonoMethod *mhandle;
- guint32 nrefs;
- gpointer *refs;
- /* for PInvoke */
- int charset, extra_flags, native_cc;
- MonoString *dll, *dllentry;
-} ReflectionMethodBuilder;
-
-typedef struct {
- guint32 owner;
- MonoReflectionGenericParam *gparam;
-} GenericParamTableEntry;
-
-const unsigned char table_sizes [MONO_TABLE_NUM] = {
- MONO_MODULE_SIZE,
- MONO_TYPEREF_SIZE,
- MONO_TYPEDEF_SIZE,
- 0,
- MONO_FIELD_SIZE,
- 0,
- MONO_METHOD_SIZE,
- 0,
- MONO_PARAM_SIZE,
- MONO_INTERFACEIMPL_SIZE,
- MONO_MEMBERREF_SIZE, /* 0x0A */
- MONO_CONSTANT_SIZE,
- MONO_CUSTOM_ATTR_SIZE,
- MONO_FIELD_MARSHAL_SIZE,
- MONO_DECL_SECURITY_SIZE,
- MONO_CLASS_LAYOUT_SIZE,
- MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
- MONO_STAND_ALONE_SIGNATURE_SIZE,
- MONO_EVENT_MAP_SIZE,
- 0,
- MONO_EVENT_SIZE,
- MONO_PROPERTY_MAP_SIZE,
- 0,
- MONO_PROPERTY_SIZE,
- MONO_METHOD_SEMA_SIZE,
- MONO_METHODIMPL_SIZE,
- MONO_MODULEREF_SIZE, /* 0x1A */
- MONO_TYPESPEC_SIZE,
- MONO_IMPLMAP_SIZE,
- MONO_FIELD_RVA_SIZE,
- 0,
- 0,
- MONO_ASSEMBLY_SIZE, /* 0x20 */
- MONO_ASSEMBLY_PROCESSOR_SIZE,
- MONO_ASSEMBLYOS_SIZE,
- MONO_ASSEMBLYREF_SIZE,
- MONO_ASSEMBLYREFPROC_SIZE,
- MONO_ASSEMBLYREFOS_SIZE,
- MONO_FILE_SIZE,
- MONO_EXP_TYPE_SIZE,
- MONO_MANIFEST_SIZE,
- MONO_NESTED_CLASS_SIZE,
-
- MONO_GENERICPARAM_SIZE, /* 0x2A */
- MONO_METHODSPEC_SIZE,
- MONO_GENPARCONSTRAINT_SIZE
-
-};
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
-static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
-static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
-static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
-static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
-static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
-static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
-static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
-static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
-static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
-static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
-static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
-#endif
-
-static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
-static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
-static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
-static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
-static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
-static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
-static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
-static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
-static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
-static gboolean is_sre_array (MonoClass *klass);
-static gboolean is_sre_byref (MonoClass *klass);
-static gboolean is_sre_pointer (MonoClass *klass);
-static gboolean is_sre_type_builder (MonoClass *klass);
-static gboolean is_sre_method_builder (MonoClass *klass);
-static gboolean is_sre_ctor_builder (MonoClass *klass);
-static gboolean is_sre_field_builder (MonoClass *klass);
-static gboolean is_sr_mono_method (MonoClass *klass);
-static gboolean is_sr_mono_cmethod (MonoClass *klass);
-static gboolean is_sr_mono_generic_method (MonoClass *klass);
-static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
-static gboolean is_sr_mono_field (MonoClass *klass);
-static gboolean is_sr_mono_property (MonoClass *klass);
-static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
-static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
-
-static gboolean type_is_reference (MonoType *type);
-
-static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
-static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
-static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
-
-static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
-static void init_type_builder_generics (MonoObject *type, MonoError *error);
-
-#define RESOLVE_TYPE(type, error) do { \
- type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
-} while (0)
-#define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
- MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
- __type = mono_reflection_type_resolve_user_types (__type, error); \
- if (mono_error_ok (error)) \
- mono_array_set (arr, MonoReflectionType*, index, __type); \
-} while (0)
-
-#define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
-
-#define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
-#define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
-
-#if SIZEOF_VOID_P == 4
-#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
-#else
-#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
-#endif
-
-#define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
-#define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
/* Class lazy loading functions */
static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
-static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
-static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
-static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
-// The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
-static GPtrArray *dynamic_images;
-static mono_mutex_t dynamic_images_mutex;
-
-static inline void
-dynamic_images_lock (void)
-{
- mono_os_mutex_lock (&dynamic_images_mutex);
-}
-
-static inline void
-dynamic_images_unlock (void)
-{
- mono_os_mutex_unlock (&dynamic_images_mutex);
-}
-
-/**
- * mono_find_dynamic_image_owner:
- *
- * Find the dynamic image, if any, which a given pointer is located in the memory of.
- */
-MonoImage *
-mono_find_dynamic_image_owner (void *ptr)
-{
- MonoImage *owner = NULL;
- int i;
-
- dynamic_images_lock ();
-
- if (dynamic_images)
- {
- for (i = 0; !owner && i < dynamic_images->len; ++i) {
- MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
- if (mono_mempool_contains_addr (image->mempool, ptr))
- owner = image;
- }
- }
-
- dynamic_images_unlock ();
-
- return owner;
-}
-
void
mono_reflection_init (void)
{
- mono_os_mutex_init (&dynamic_images_mutex);
-}
-
-static inline void
-dynamic_image_lock (MonoDynamicImage *image)
-{
- MONO_ENTER_GC_SAFE;
- mono_image_lock ((MonoImage*)image);
- MONO_EXIT_GC_SAFE;
-}
-
-static inline void
-dynamic_image_unlock (MonoDynamicImage *image)
-{
- mono_image_unlock ((MonoImage*)image);
+ mono_reflection_emit_init ();
}
-static void
-register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
+/*
+ * mono_class_get_ref_info:
+ *
+ * Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ */
+gpointer
+mono_class_get_ref_info (MonoClass *klass)
{
MONO_REQ_GC_UNSAFE_MODE;
- dynamic_image_lock (assembly);
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
- dynamic_image_unlock (assembly);
+ if (klass->ref_info_handle == 0)
+ return NULL;
+ else
+ return mono_gchandle_get_target (klass->ref_info_handle);
}
-static MonoObject*
-lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
+void
+mono_class_set_ref_info (MonoClass *klass, gpointer obj)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoObject *obj;
-
- dynamic_image_lock (assembly);
- obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
- dynamic_image_unlock (assembly);
-
- return obj;
+ klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
+ g_assert (klass->ref_info_handle != 0);
}
-static void
-sigbuffer_init (SigBuffer *buf, int size)
+void
+mono_class_free_ref_info (MonoClass *klass)
{
MONO_REQ_GC_NEUTRAL_MODE;
- buf->buf = (char *)g_malloc (size);
- buf->p = buf->buf;
- buf->end = buf->buf + size;
+ if (klass->ref_info_handle) {
+ mono_gchandle_free (klass->ref_info_handle);
+ klass->ref_info_handle = 0;
+ }
}
-static void
-sigbuffer_make_room (SigBuffer *buf, int size)
+
+void
+mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
{
MONO_REQ_GC_NEUTRAL_MODE;
- if (buf->end - buf->p < size) {
- int new_size = buf->end - buf->buf + size + 32;
- char *p = (char *)g_realloc (buf->buf, new_size);
- size = buf->p - buf->buf;
- buf->buf = p;
- buf->p = p + size;
- buf->end = buf->buf + new_size;
- }
+ if (ainfo && !ainfo->cached)
+ g_free (ainfo);
}
-static void
-sigbuffer_add_value (SigBuffer *buf, guint32 val)
+
+gboolean
+reflected_equal (gconstpointer a, gconstpointer b)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ const ReflectedEntry *ea = (const ReflectedEntry *)a;
+ const ReflectedEntry *eb = (const ReflectedEntry *)b;
- sigbuffer_make_room (buf, 6);
- mono_metadata_encode_value (val, buf->p, &buf->p);
+ return (ea->item == eb->item) && (ea->refclass == eb->refclass);
}
-static void
-sigbuffer_add_byte (SigBuffer *buf, guint8 val)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- sigbuffer_make_room (buf, 1);
- buf->p [0] = val;
- buf->p++;
+guint
+reflected_hash (gconstpointer a) {
+ const ReflectedEntry *ea = (const ReflectedEntry *)a;
+ return mono_aligned_addr_hash (ea->item);
}
+
static void
-sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
+clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ mono_domain_lock (domain);
+ if (domain->refobject_hash) {
+ ReflectedEntry pe;
+ gpointer orig_pe, orig_value;
- sigbuffer_make_room (buf, size);
- memcpy (buf->p, p, size);
- buf->p += size;
+ pe.item = o;
+ pe.refclass = klass;
+ if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
+ mono_g_hash_table_remove (domain->refobject_hash, &pe);
+ FREE_REFENTRY (orig_pe);
+ }
+ }
+ mono_domain_unlock (domain);
}
+#ifdef REFENTRY_REQUIRES_CLEANUP
static void
-sigbuffer_free (SigBuffer *buf)
+cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- g_free (buf->buf);
+ FREE_REFENTRY (key);
}
+#endif
-#ifndef DISABLE_REFLECTION_EMIT
-/**
- * mp_g_alloc:
- *
- * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
- * from the C heap.
- */
-static gpointer
-image_g_malloc (MonoImage *image, guint size)
+void
+mono_reflection_cleanup_domain (MonoDomain *domain)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (image)
- return mono_image_alloc (image, size);
- else
- return g_malloc (size);
+ if (domain->refobject_hash) {
+/*let's avoid scanning the whole hashtable if not needed*/
+#ifdef REFENTRY_REQUIRES_CLEANUP
+ mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
+#endif
+ mono_g_hash_table_destroy (domain->refobject_hash);
+ domain->refobject_hash = NULL;
+ }
}
-#endif /* !DISABLE_REFLECTION_EMIT */
-/**
- * image_g_alloc0:
+
+/*
+ * mono_assembly_get_object:
+ * @domain: an app domain
+ * @assembly: an assembly
*
- * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
- * from the C heap.
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
*/
-static gpointer
-image_g_malloc0 (MonoImage *image, guint size)
+MonoReflectionAssembly*
+mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (image)
- return mono_image_alloc0 (image, size);
- else
- return g_malloc0 (size);
+ MonoError error;
+ MonoReflectionAssembly *result;
+ result = mono_assembly_get_object_checked (domain, assembly, &error);
+ mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
+ return result;
}
-
-/**
- * image_g_free:
- * @image: a MonoImage
- * @ptr: pointer
+/*
+ * mono_assembly_get_object_checked:
+ * @domain: an app domain
+ * @assembly: an assembly
*
- * If @image is NULL, free @ptr, otherwise do nothing.
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
*/
-static void
-image_g_free (MonoImage *image, gpointer ptr)
+MonoReflectionAssembly*
+mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
{
- if (image == NULL)
- g_free (ptr);
-}
+ MonoReflectionAssembly *res;
+
+ mono_error_init (error);
-#ifndef DISABLE_REFLECTION_EMIT
-static char*
-image_strdup (MonoImage *image, const char *s)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
+ res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
+ if (!res)
+ return NULL;
+ res->assembly = assembly;
- if (image)
- return mono_image_strdup (image, s);
- else
- return g_strdup (s);
+ CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
}
-#endif
-
-#define image_g_new(image,struct_type, n_structs) \
- ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define image_g_new0(image,struct_type, n_structs) \
- ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-static void
-alloc_table (MonoDynamicTable *table, guint nrows)
+MonoReflectionModule*
+mono_module_get_object (MonoDomain *domain, MonoImage *image)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- table->rows = nrows;
- g_assert (table->columns);
- if (nrows + 1 >= table->alloc_rows) {
- while (nrows + 1 >= table->alloc_rows) {
- if (table->alloc_rows == 0)
- table->alloc_rows = 16;
- else
- table->alloc_rows *= 2;
- }
-
- table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
- }
+ MonoError error;
+ MonoReflectionModule *result;
+ result = mono_module_get_object_checked (domain, image, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-static void
-make_room_in_stream (MonoDynamicStream *stream, int size)
+MonoReflectionModule*
+mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (size <= stream->alloc_size)
- return;
-
- while (stream->alloc_size <= size) {
- if (stream->alloc_size < 4096)
- stream->alloc_size = 4096;
- else
- stream->alloc_size *= 2;
- }
+ MonoReflectionModule *res;
+ char* basename;
- stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
-}
-
-static guint32
-string_heap_insert (MonoDynamicStream *sh, const char *str)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
- guint32 len;
- gpointer oldkey, oldval;
+ mono_error_init (error);
+ CHECK_OBJECT (MonoReflectionModule *, image, NULL);
+ res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
+ if (!res)
+ return NULL;
- if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
- return GPOINTER_TO_UINT (oldval);
+ res->image = image;
+ MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
+ if (!assm_obj)
+ return NULL;
+ MONO_OBJECT_SETREF (res, assembly, assm_obj);
- len = strlen (str) + 1;
- idx = sh->index;
+ MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
+ basename = g_path_get_basename (image->name);
+ MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
+ MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
- make_room_in_stream (sh, idx + len);
-
- /*
- * We strdup the string even if we already copy them in sh->data
- * so that the string pointers in the hash remain valid even if
- * we need to realloc sh->data. We may want to avoid that later.
- */
- g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
- memcpy (sh->data + idx, str, len);
- sh->index += len;
- return idx;
-}
+ g_free (basename);
-static guint32
-string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ if (image->assembly->image == image) {
+ res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
+ } else {
+ int i;
+ res->token = 0;
+ if (image->assembly->image->modules) {
+ for (i = 0; i < image->assembly->image->module_count; i++) {
+ if (image->assembly->image->modules [i] == image)
+ res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+ }
+ g_assert (res->token);
+ }
+ }
- mono_error_init (error);
- char *name = mono_string_to_utf8_checked (str, error);
- return_val_if_nok (error, -1);
- guint32 idx;
- idx = string_heap_insert (sh, name);
- g_free (name);
- return idx;
+ CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
}
-#ifndef DISABLE_REFLECTION_EMIT
-static void
-string_heap_init (MonoDynamicStream *sh)
+MonoReflectionModule*
+mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- sh->index = 0;
- sh->alloc_size = 4096;
- sh->data = (char *)g_malloc (4096);
- sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- string_heap_insert (sh, "");
+ MonoError error;
+ MonoReflectionModule *result;
+ result = mono_module_file_get_object_checked (domain, image, table_index, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-#endif
-static guint32
-mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+MonoReflectionModule*
+mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
+ MonoReflectionModule *res;
+ MonoTableInfo *table;
+ guint32 cols [MONO_FILE_SIZE];
+ const char *name;
+ guint32 i, name_idx;
+ const char *val;
- make_room_in_stream (stream, stream->index + len);
- memcpy (stream->data + stream->index, data, len);
- idx = stream->index;
- stream->index += len;
- /*
- * align index? Not without adding an additional param that controls it since
- * we may store a blob value in pieces.
- */
- return idx;
-}
+ mono_error_init (error);
-static guint32
-mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
-
- make_room_in_stream (stream, stream->index + len);
- memset (stream->data + stream->index, 0, len);
- idx = stream->index;
- stream->index += len;
- return idx;
-}
-
-static void
-stream_data_align (MonoDynamicStream *stream)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- char buf [4] = {0};
- guint32 count = stream->index % 4;
+ res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
+ if (!res)
+ return NULL;
- /* we assume the stream data will be aligned */
- if (count)
- mono_image_add_stream_data (stream, buf, 4 - count);
-}
+ table = &image->tables [MONO_TABLE_FILE];
+ g_assert (table_index < table->rows);
+ mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
-#ifndef DISABLE_REFLECTION_EMIT
-static int
-mono_blob_entry_hash (const char* str)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ res->image = NULL;
+ MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
+ if (!assm_obj)
+ return NULL;
+ MONO_OBJECT_SETREF (res, assembly, assm_obj);
+ name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
- guint len, h;
- const char *end;
- len = mono_metadata_decode_blob_size (str, &str);
- if (len > 0) {
- end = str + len;
- h = *str;
- for (str += 1; str < end; str++)
- h = (h << 5) - h + *str;
- return h;
- } else {
- return 0;
+ /* Check whenever the row has a corresponding row in the moduleref table */
+ table = &image->tables [MONO_TABLE_MODULEREF];
+ for (i = 0; i < table->rows; ++i) {
+ name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
+ val = mono_metadata_string_heap (image, name_idx);
+ if (strcmp (val, name) == 0)
+ res->image = image->modules [i];
}
-}
-
-static gboolean
-mono_blob_entry_equal (const char *str1, const char *str2) {
- MONO_REQ_GC_NEUTRAL_MODE;
- int len, len2;
- const char *end1;
- const char *end2;
- len = mono_metadata_decode_blob_size (str1, &end1);
- len2 = mono_metadata_decode_blob_size (str2, &end2);
- if (len != len2)
- return 0;
- return memcmp (end1, end2, len) == 0;
-}
-#endif
-static guint32
-add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
- char *copy;
- gpointer oldkey, oldval;
+ MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
+ MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
+ MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
+ res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
+ res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
- copy = (char *)g_malloc (s1+s2);
- memcpy (copy, b1, s1);
- memcpy (copy + s1, b2, s2);
- if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
- g_free (copy);
- idx = GPOINTER_TO_UINT (oldval);
- } else {
- idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
- mono_image_add_stream_data (&assembly->blob, b2, s2);
- g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
- }
- return idx;
+ return res;
}
-static guint32
-sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
+static gboolean
+verify_safe_for_managed_space (MonoType *type)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- char blob_size [8];
- char *b = blob_size;
- guint32 size = buf->p - buf->buf;
- /* store length */
- g_assert (size <= (buf->end - buf->buf));
- mono_metadata_encode_value (size, b, &b);
- return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
-}
-
-/*
- * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
- * dest may be misaligned.
- */
-static void
-swap_with_size (char *dest, const char* val, int len, int nelem) {
- MONO_REQ_GC_NEUTRAL_MODE;
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- int elem;
-
- for (elem = 0; elem < nelem; ++elem) {
- switch (len) {
- case 1:
- *dest = *val;
- break;
- case 2:
- dest [0] = val [1];
- dest [1] = val [0];
- break;
- case 4:
- dest [0] = val [3];
- dest [1] = val [2];
- dest [2] = val [1];
- dest [3] = val [0];
- break;
- case 8:
- dest [0] = val [7];
- dest [1] = val [6];
- dest [2] = val [5];
- dest [3] = val [4];
- dest [4] = val [3];
- dest [5] = val [2];
- dest [6] = val [1];
- dest [7] = val [0];
+ switch (type->type) {
+#ifdef DEBUG_HARDER
+ case MONO_TYPE_ARRAY:
+ return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
+ case MONO_TYPE_PTR:
+ return verify_safe_for_managed_space (type->data.type);
+ case MONO_TYPE_SZARRAY:
+ return verify_safe_for_managed_space (&type->data.klass->byval_arg);
+ case MONO_TYPE_GENERICINST: {
+ MonoGenericInst *inst = type->data.generic_class->inst;
+ int i;
+ if (!inst->is_open)
break;
- default:
- g_assert_not_reached ();
- }
- dest += len;
- val += len;
+ for (i = 0; i < inst->type_argc; ++i)
+ if (!verify_safe_for_managed_space (inst->type_argv [i]))
+ return FALSE;
+ return TRUE;
}
-#else
- memcpy (dest, val, len * nelem);
#endif
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ return TRUE;
+ default:
+ return TRUE;
+ }
}
-static guint32
-add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
+static MonoType*
+mono_type_normalize (MonoType *type)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- char blob_size [64];
- char *b = blob_size;
- guint32 idx = 0, len;
+ int i;
+ MonoGenericClass *gclass;
+ MonoGenericInst *ginst;
+ MonoClass *gtd;
+ MonoGenericContainer *gcontainer;
+ MonoType **argv = NULL;
+ gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
- len = str->length * 2;
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
+ if (type->type != MONO_TYPE_GENERICINST)
+ return type;
+
+ gclass = type->data.generic_class;
+ ginst = gclass->context.class_inst;
+ if (!ginst->is_open)
+ return type;
+
+ gtd = gclass->container_class;
+ gcontainer = gtd->generic_container;
+ argv = g_newa (MonoType*, ginst->type_argc);
- swap_with_size (swapped, p, 2, mono_string_length (str));
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
- g_free (swapped);
+ for (i = 0; i < ginst->type_argc; ++i) {
+ MonoType *t = ginst->type_argv [i], *norm;
+ if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
+ is_denorm_gtd = FALSE;
+ norm = mono_type_normalize (t);
+ argv [i] = norm;
+ if (norm != t)
+ requires_rebind = TRUE;
}
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
-#endif
- return idx;
-}
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoClass *
-default_class_from_mono_type (MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ if (is_denorm_gtd)
+ return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
- switch (type->type) {
- case MONO_TYPE_OBJECT:
- return mono_defaults.object_class;
- case MONO_TYPE_VOID:
- return mono_defaults.void_class;
- case MONO_TYPE_BOOLEAN:
- return mono_defaults.boolean_class;
- case MONO_TYPE_CHAR:
- return mono_defaults.char_class;
- case MONO_TYPE_I1:
- return mono_defaults.sbyte_class;
- case MONO_TYPE_U1:
- return mono_defaults.byte_class;
- case MONO_TYPE_I2:
- return mono_defaults.int16_class;
- case MONO_TYPE_U2:
- return mono_defaults.uint16_class;
- case MONO_TYPE_I4:
- return mono_defaults.int32_class;
- case MONO_TYPE_U4:
- return mono_defaults.uint32_class;
- case MONO_TYPE_I:
- return mono_defaults.int_class;
- case MONO_TYPE_U:
- return mono_defaults.uint_class;
- case MONO_TYPE_I8:
- return mono_defaults.int64_class;
- case MONO_TYPE_U8:
- return mono_defaults.uint64_class;
- case MONO_TYPE_R4:
- return mono_defaults.single_class;
- case MONO_TYPE_R8:
- return mono_defaults.double_class;
- case MONO_TYPE_STRING:
- return mono_defaults.string_class;
- default:
- g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
- g_assert_not_reached ();
+ if (requires_rebind) {
+ MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
+ return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
}
-
- return NULL;
-}
-#endif
+ return type;
+}
/*
- * mono_class_get_ref_info:
+ * mono_type_get_object:
+ * @domain: an app domain
+ * @type: a type
*
- * Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ * Return an System.MonoType object representing the type @type.
*/
-gpointer
-mono_class_get_ref_info (MonoClass *klass)
+MonoReflectionType*
+mono_type_get_object (MonoDomain *domain, MonoType *type)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
+ mono_error_cleanup (&error);
- if (klass->ref_info_handle == 0)
- return NULL;
- else
- return mono_gchandle_get_target (klass->ref_info_handle);
+ return ret;
}
-void
-mono_class_set_ref_info (MonoClass *klass, gpointer obj)
+MonoReflectionType*
+mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoType *norm_type;
+ MonoReflectionType *res;
+ MonoClass *klass;
- klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
- g_assert (klass->ref_info_handle != 0);
-}
+ mono_error_init (error);
-void
-mono_class_free_ref_info (MonoClass *klass)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ klass = mono_class_from_mono_type (type);
- if (klass->ref_info_handle) {
- mono_gchandle_free (klass->ref_info_handle);
- klass->ref_info_handle = 0;
- }
-}
+ /*we must avoid using @type as it might have come
+ * from a mono_metadata_type_dup and the caller
+ * expects that is can be freed.
+ * Using the right type from
+ */
+ type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
-static void
-encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ /* void is very common */
+ if (type->type == MONO_TYPE_VOID && domain->typeof_void)
+ return (MonoReflectionType*)domain->typeof_void;
- int i;
- MonoGenericInst *class_inst;
- MonoClass *klass;
+ /*
+ * If the vtable of the given class was already created, we can use
+ * the MonoType from there and avoid all locking and hash table lookups.
+ *
+ * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
+ * that the resulting object is different.
+ */
+ if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
+ MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
+ if (vtable && vtable->type)
+ return (MonoReflectionType *)vtable->type;
+ }
- g_assert (gclass);
+ mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
+ mono_domain_lock (domain);
+ if (!domain->type_hash)
+ domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
+ (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
+ if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
+ }
- class_inst = gclass->context.class_inst;
+ /*Types must be normalized so a generic instance of the GTD get's the same inner type.
+ * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
+ * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
+ * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
+ * artifact of how generics are encoded and should be transparent to managed code so we
+ * need to weed out this diference when retrieving managed System.Type objects.
+ */
+ norm_type = mono_type_normalize (type);
+ if (norm_type != type) {
+ res = mono_type_get_object_checked (domain, norm_type, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ mono_g_hash_table_insert (domain->type_hash, type, res);
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
+ }
- sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
- klass = gclass->container_class;
- sigbuffer_add_value (buf, klass->byval_arg.type);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
+ /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
+ if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
+ g_assert (0);
- sigbuffer_add_value (buf, class_inst->type_argc);
- for (i = 0; i < class_inst->type_argc; ++i)
- encode_type (assembly, class_inst->type_argv [i], buf);
+ if (!verify_safe_for_managed_space (type)) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
+ return NULL;
+ }
-}
+ if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
+ gboolean is_type_done = TRUE;
+ /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
+ * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
+ * We can't simply close the types as this will interfere with other parts of the generics machinery.
+ */
+ if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
+ MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
-static void
-encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ if (gparam->owner && gparam->owner->is_method) {
+ MonoMethod *method = gparam->owner->owner.method;
+ if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
+ is_type_done = FALSE;
+ } else if (gparam->owner && !gparam->owner->is_method) {
+ MonoClass *klass = gparam->owner->owner.klass;
+ if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
+ is_type_done = FALSE;
+ }
+ }
- if (!type) {
- g_assert_not_reached ();
- return;
- }
-
- if (type->byref)
- sigbuffer_add_value (buf, MONO_TYPE_BYREF);
-
- switch (type->type){
- case MONO_TYPE_VOID:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_STRING:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_TYPEDBYREF:
- sigbuffer_add_value (buf, type->type);
- break;
- case MONO_TYPE_PTR:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, type->data.type, buf);
- break;
- case MONO_TYPE_SZARRAY:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, &type->data.klass->byval_arg, buf);
- break;
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_CLASS: {
- MonoClass *k = mono_class_from_mono_type (type);
-
- if (k->generic_container) {
- MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
- encode_generic_class (assembly, gclass, buf);
- } else {
- /*
- * Make sure we use the correct type.
- */
- sigbuffer_add_value (buf, k->byval_arg.type);
- /*
- * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
- * otherwise two typerefs could point to the same type, leading to
- * verification errors.
- */
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
+ /* g_assert_not_reached (); */
+ /* should this be considered an error condition? */
+ if (is_type_done && !type->byref) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return (MonoReflectionType *)mono_class_get_ref_info (klass);
}
- break;
- }
- case MONO_TYPE_ARRAY:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
- sigbuffer_add_value (buf, type->data.array->rank);
- sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
- sigbuffer_add_value (buf, 0);
- break;
- case MONO_TYPE_GENERICINST:
- encode_generic_class (assembly, type->data.generic_class, buf);
- break;
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- sigbuffer_add_value (buf, type->type);
- sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
- break;
- default:
- g_error ("need to encode type %x", type->type);
}
-}
-
-static void
-encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ /* This is stored in vtables/JITted code so it has to be pinned */
+ res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
+ if (!mono_error_ok (error))
+ return NULL;
- mono_error_init (error);
+ res->type = type;
+ mono_g_hash_table_insert (domain->type_hash, type, res);
- if (!type) {
- sigbuffer_add_value (buf, MONO_TYPE_VOID);
- return;
- }
+ if (type->type == MONO_TYPE_VOID)
+ domain->typeof_void = (MonoObject*)res;
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_if_nok (error);
- encode_type (assembly, t, buf);
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
}
-static void
-encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
+/*
+ * mono_method_get_object:
+ * @domain: an app domain
+ * @method: a method
+ * @refclass: the reflected type (can be NULL)
+ *
+ * Return an System.Reflection.MonoMethod object representing the method @method.
+ */
+MonoReflectionMethod*
+mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- int i;
-
- mono_error_init (error);
-
- if (modreq) {
- for (i = 0; i < mono_array_length (modreq); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
- return_if_nok (error);
- sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
- }
- }
- if (modopt) {
- for (i = 0; i < mono_array_length (modopt); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
- return_if_nok (error);
- sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
- }
- }
+ MonoError error;
+ MonoReflectionMethod *ret = NULL;
+ ret = mono_method_get_object_checked (domain, method, refclass, &error);
+ mono_error_cleanup (&error);
+ return ret;
}
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
+/*
+ * mono_method_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @refclass: the reflected type (can be NULL)
+ * @error: set on error.
+ *
+ * Return an System.Reflection.MonoMethod object representing the method @method.
+ * Returns NULL and sets @error on error.
+ */
+MonoReflectionMethod*
+mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- SigBuffer buf;
- int i;
- guint32 nparams = sig->param_count;
- guint32 idx;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
/*
- * FIXME: vararg, explicit_this, differenc call_conv values...
+ * We use the same C representation for methods and constructors, but the type
+ * name in C# is different.
*/
- idx = sig->call_convention;
- if (sig->hasthis)
- idx |= 0x20; /* hasthis */
- if (sig->generic_param_count)
- idx |= 0x10; /* generic */
- sigbuffer_add_byte (&buf, idx);
- if (sig->generic_param_count)
- sigbuffer_add_value (&buf, sig->generic_param_count);
- sigbuffer_add_value (&buf, nparams);
- encode_type (assembly, sig->ret, &buf);
- for (i = 0; i < nparams; ++i) {
- if (i == sig->sentinelpos)
- sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
- encode_type (assembly, sig->params [i], &buf);
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-#endif
-
-static guint32
-method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoReflectionType *rt;
+ MonoClass *klass;
+ MonoReflectionMethod *ret;
mono_error_init (error);
- /*
- * FIXME: reuse code from method_encode_signature().
- */
- SigBuffer buf;
- int i;
- guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
- guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
- guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
- guint32 idx;
-
- sigbuffer_init (&buf, 32);
- /* LAMESPEC: all the call conv spec is foobared */
- idx = mb->call_conv & 0x60; /* has-this, explicit-this */
- if (mb->call_conv & 2)
- idx |= 0x5; /* vararg */
- if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
- idx |= 0x20; /* hasthis */
- if (ngparams)
- idx |= 0x10; /* generic */
- sigbuffer_add_byte (&buf, idx);
- if (ngparams)
- sigbuffer_add_value (&buf, ngparams);
- sigbuffer_add_value (&buf, nparams + notypes);
- encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
- if (!is_ok (error))
- goto leave;
- encode_reflection_type (assembly, mb->rtype, &buf, error);
- if (!is_ok (error))
- goto leave;
- for (i = 0; i < nparams; ++i) {
- MonoArray *modreq = NULL;
- MonoArray *modopt = NULL;
- MonoReflectionType *pt;
-
- if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
- modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
- if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
- modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
- encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
- if (!is_ok (error))
- goto leave;
- pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto leave;
- }
- if (notypes)
- sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
- for (i = 0; i < notypes; ++i) {
- MonoReflectionType *pt;
+ if (method->is_inflated) {
+ MonoReflectionGenericMethod *gret;
- pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
+ if (!refclass)
+ refclass = method->klass;
+ CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
+ if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
+ klass = mono_class_get_mono_generic_cmethod_class ();
+ } else {
+ klass = mono_class_get_mono_generic_method_class ();
+ }
+ gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
+ if (!mono_error_ok (error))
goto leave;
- }
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
-leave:
- sigbuffer_free (&buf);
- return idx;
-}
+ gret->method.method = method;
-static guint32
-encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
- mono_error_init (error);
+ rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
+ if (!mono_error_ok (error))
+ goto leave;
- MonoDynamicTable *table;
- guint32 *values;
- guint32 idx, sig_idx;
- guint nl = mono_array_length (ilgen->locals);
- SigBuffer buf;
- int i;
+ MONO_OBJECT_SETREF (gret, method.reftype, rt);
- sigbuffer_init (&buf, 32);
- sigbuffer_add_value (&buf, 0x07);
- sigbuffer_add_value (&buf, nl);
- for (i = 0; i < nl; ++i) {
- MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
-
- if (lb->is_pinned)
- sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
-
- encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
+ CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
}
- sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- if (assembly->standalonesig_cache == NULL)
- assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
- if (idx)
- return idx;
+ if (!refclass)
+ refclass = method->klass;
+
+ CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
+ if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
+ klass = mono_class_get_mono_cmethod_class ();
+ }
+ else {
+ klass = mono_class_get_mono_method_class ();
+ }
+ ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
+ if (!mono_error_ok (error))
+ goto leave;
+ ret->method = method;
- table = &assembly->tables [MONO_TABLE_STANDALONESIG];
- idx = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
+ rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
+ if (!mono_error_ok (error))
+ goto leave;
- values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
+ MONO_OBJECT_SETREF (ret, reftype, rt);
- g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
+ CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
- return idx;
+leave:
+ g_assert (!mono_error_ok (error));
+ return NULL;
}
-static guint32
-method_count_clauses (MonoReflectionILGen *ilgen)
+/*
+ * mono_method_clear_object:
+ *
+ * Clear the cached reflection objects for the dynamic method METHOD.
+ */
+void
+mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- guint32 num_clauses = 0;
- int i;
+ MonoClass *klass;
+ g_assert (method_is_dynamic (method));
- MonoILExceptionInfo *ex_info;
- for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers)
- num_clauses += mono_array_length (ex_info->handlers);
- else
- num_clauses++;
+ klass = method->klass;
+ while (klass) {
+ clear_cached_object (domain, method, klass);
+ klass = klass->parent;
+ }
+ /* Added by mono_param_get_objects () */
+ clear_cached_object (domain, &(method->signature), NULL);
+ klass = method->klass;
+ while (klass) {
+ clear_cached_object (domain, &(method->signature), klass);
+ klass = klass->parent;
}
-
- return num_clauses;
}
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoExceptionClause*
-method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
+/*
+ * mono_field_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @field: a field
+ *
+ * Return an System.Reflection.MonoField object representing the field @field
+ * in class @klass.
+ */
+MonoReflectionField*
+mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- MonoExceptionClause *clauses;
- MonoExceptionClause *clause;
- MonoILExceptionInfo *ex_info;
- MonoILExceptionBlock *ex_block;
- guint32 finally_start;
- int i, j, clause_index;;
-
- clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
-
- clause_index = 0;
- for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
- finally_start = ex_info->start + ex_info->len;
- if (!ex_info->handlers)
- continue;
- for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
- ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
- clause = &(clauses [clause_index]);
-
- clause->flags = ex_block->type;
- clause->try_offset = ex_info->start;
-
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
- clause->try_len = finally_start - ex_info->start;
- else
- clause->try_len = ex_info->len;
- clause->handler_offset = ex_block->start;
- clause->handler_len = ex_block->len;
- if (ex_block->extype) {
- MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
-
- if (!is_ok (error)) {
- image_g_free (image, clauses);
- return NULL;
- }
- clause->data.catch_class = mono_class_from_mono_type (extype);
- } else {
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
- clause->data.filter_offset = ex_block->filter_offset;
- else
- clause->data.filter_offset = 0;
- }
- finally_start = ex_block->start + ex_block->len;
-
- clause_index ++;
- }
- }
-
- return clauses;
+ MonoError error;
+ MonoReflectionField *result;
+ result = mono_field_get_object_checked (domain, klass, field, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-#endif /* !DISABLE_REFLECTION_EMIT */
-/**
- * method_encode_code:
- *
- * @assembly the assembly
- * @mb the managed MethodBuilder
- * @error set on error
+/*
+ * mono_field_get_object_checked:
+ * @domain: an app domain
+ * @klass: a type
+ * @field: a field
+ * @error: set on error
*
- * Note that the return value is not sensible if @error is set.
+ * Return an System.Reflection.MonoField object representing the field @field
+ * in class @klass. On error, returns NULL and sets @error.
*/
-static guint32
-method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
+MonoReflectionField*
+mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- char flags = 0;
- guint32 idx;
- guint32 code_size;
- gint32 max_stack, i;
- gint32 num_locals = 0;
- gint32 num_exception = 0;
- gint maybe_small;
- guint32 fat_flags;
- char fat_header [12];
- guint32 int_value;
- guint16 short_value;
- guint32 local_sig = 0;
- guint32 header_size = 12;
- MonoArray *code;
+ MonoReflectionType *rt;
+ MonoReflectionField *res;
mono_error_init (error);
- if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
- (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
- return 0;
-
- /*if (mb->name)
- g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
- if (mb->ilgen) {
- code = mb->ilgen->code;
- code_size = mb->ilgen->code_len;
- max_stack = mb->ilgen->max_stack;
- num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
- if (mb->ilgen->ex_handlers)
- num_exception = method_count_clauses (mb->ilgen);
- } else {
- code = mb->code;
- if (code == NULL){
- MonoError inner_error;
- char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
- if (!is_ok (&inner_error)) {
- name = g_strdup ("");
- mono_error_cleanup (&inner_error);
- }
- char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
- mono_error_set_argument (error, NULL, "a method does not have any IL associated");
- g_free (str);
- g_free (name);
- return 0;
- }
-
- code_size = mono_array_length (code);
- max_stack = 8; /* we probably need to run a verifier on the code... */
- }
+ CHECK_OBJECT (MonoReflectionField *, field, klass);
+ res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
+ if (!res)
+ return NULL;
+ res->klass = klass;
+ res->field = field;
+ MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
- stream_data_align (&assembly->code);
+ if (field->type) {
+ rt = mono_type_get_object_checked (domain, field->type, error);
+ if (!mono_error_ok (error))
+ return NULL;
- /* check for exceptions, maxstack, locals */
- maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
- if (maybe_small) {
- if (code_size < 64 && !(code_size & 1)) {
- flags = (code_size << 2) | 0x2;
- } else if (code_size < 32 && (code_size & 1)) {
- flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
- } else {
- goto fat_header;
- }
- idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
- /* add to the fixup todo list */
- if (mb->ilgen && mb->ilgen->num_token_fixups)
- mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
- mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
- return assembly->text_rva + idx;
- }
-fat_header:
- if (num_locals) {
- local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
- return_val_if_nok (error, 0);
- }
- /*
- * FIXME: need to set also the header size in fat_flags.
- * (and more sects and init locals flags)
- */
- fat_flags = 0x03;
- if (num_exception)
- fat_flags |= METHOD_HEADER_MORE_SECTS;
- if (mb->init_locals)
- fat_flags |= METHOD_HEADER_INIT_LOCALS;
- fat_header [0] = fat_flags;
- fat_header [1] = (header_size / 4 ) << 4;
- short_value = GUINT16_TO_LE (max_stack);
- memcpy (fat_header + 2, &short_value, 2);
- int_value = GUINT32_TO_LE (code_size);
- memcpy (fat_header + 4, &int_value, 4);
- int_value = GUINT32_TO_LE (local_sig);
- memcpy (fat_header + 8, &int_value, 4);
- idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
- /* add to the fixup todo list */
- if (mb->ilgen && mb->ilgen->num_token_fixups)
- mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
-
- mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
- if (num_exception) {
- unsigned char sheader [4];
- MonoILExceptionInfo * ex_info;
- MonoILExceptionBlock * ex_block;
- int j;
-
- stream_data_align (&assembly->code);
- /* always use fat format for now */
- sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
- num_exception *= 6 * sizeof (guint32);
- num_exception += 4; /* include the size of the header */
- sheader [1] = num_exception & 0xff;
- sheader [2] = (num_exception >> 8) & 0xff;
- sheader [3] = (num_exception >> 16) & 0xff;
- mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
- /* fat header, so we are already aligned */
- /* reverse order */
- for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
- ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers) {
- int finally_start = ex_info->start + ex_info->len;
- for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
- guint32 val;
- ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
- /* the flags */
- val = GUINT32_TO_LE (ex_block->type);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* try offset */
- val = GUINT32_TO_LE (ex_info->start);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* need fault, too, probably */
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
- val = GUINT32_TO_LE (finally_start - ex_info->start);
- else
- val = GUINT32_TO_LE (ex_info->len);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* handler offset */
- val = GUINT32_TO_LE (ex_block->start);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* handler len */
- val = GUINT32_TO_LE (ex_block->len);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- finally_start = ex_block->start + ex_block->len;
- if (ex_block->extype) {
- MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
- return_val_if_nok (error, 0);
-
- val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
- } else {
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
- val = ex_block->filter_offset;
- else
- val = 0;
- }
- val = GUINT32_TO_LE (val);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
- clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
- }
- } else {
- g_error ("No clauses for ex info block %d", i);
- }
- }
+ MONO_OBJECT_SETREF (res, type, rt);
}
- return assembly->text_rva + idx;
+ res->attrs = mono_field_get_flags (field);
+ CACHE_OBJECT (MonoReflectionField *, field, res, klass);
}
-static guint32
-find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
+/*
+ * mono_property_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @property: a property
+ *
+ * Return an System.Reflection.MonoProperty object representing the property @property
+ * in class @klass.
+ */
+MonoReflectionProperty*
+mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- int i;
- MonoDynamicTable *table;
- guint32 *values;
-
- table = &assembly->tables [table_idx];
-
- g_assert (col < table->columns);
-
- values = table->values + table->columns;
- for (i = 1; i <= table->rows; ++i) {
- if (values [col] == token)
- return i;
- values += table->columns;
- }
- return 0;
+ MonoError error;
+ MonoReflectionProperty *result;
+ result = mono_property_get_object_checked (domain, klass, property, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-/*
- * LOCKING: Acquires the loader lock.
+/**
+ * mono_property_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @property: a property
+ * @error: set on error
+ *
+ * Return an System.Reflection.MonoProperty object representing the property @property
+ * in class @klass. On error returns NULL and sets @error.
*/
-static MonoCustomAttrInfo*
-lookup_custom_attr (MonoImage *image, gpointer member)
+MonoReflectionProperty*
+mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- MonoCustomAttrInfo* res;
+ MonoReflectionProperty *res;
- res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
+ mono_error_init (error);
+ CHECK_OBJECT (MonoReflectionProperty *, property, klass);
+ res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
if (!res)
return NULL;
-
- res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
- res->cached = 0;
- return res;
+ res->klass = klass;
+ res->property = property;
+ CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
}
-static gboolean
-custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
+/*
+ * mono_event_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @event: a event
+ *
+ * Return an System.Reflection.MonoEvent object representing the event @event
+ * in class @klass.
+ */
+MonoReflectionEvent*
+mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- /* FIXME: Need to do more checks */
- if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
- int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
-
- if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
- return FALSE;
- }
-
- return TRUE;
+ MonoError error;
+ MonoReflectionEvent *result;
+ result = mono_event_get_object_checked (domain, klass, event, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-static MonoCustomAttrInfo*
-mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
+/**
+ * mono_event_get_object_checked:
+ * @domain: an app domain
+ * @klass: a type
+ * @event: a event
+ * @error: set on error
+ *
+ * Return an System.Reflection.MonoEvent object representing the event @event
+ * in class @klass. On failure sets @error and returns NULL
+ */
+MonoReflectionEvent*
+mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- int i, index, count, not_visible;
- MonoCustomAttrInfo *ainfo;
- MonoReflectionCustomAttr *cattr;
+ MonoReflectionEvent *res;
+ MonoReflectionMonoEvent *mono_event;
- if (!cattrs)
+ mono_error_init (error);
+ CHECK_OBJECT (MonoReflectionEvent *, event, klass);
+ mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
+ if (!mono_event)
return NULL;
- /* FIXME: check in assembly the Run flag is set */
-
- count = mono_array_length (cattrs);
-
- /* Skip nonpublic attributes since MS.NET seems to do the same */
- /* FIXME: This needs to be done more globally */
- not_visible = 0;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- if (!custom_attr_visible (image, cattr))
- not_visible ++;
- }
-
- int num_attrs = count - not_visible;
- ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
-
- ainfo->image = image;
- ainfo->num_attrs = num_attrs;
- ainfo->cached = alloc_img != NULL;
- index = 0;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- if (custom_attr_visible (image, cattr)) {
- unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
- memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
- ainfo->attrs [index].ctor = cattr->ctor->method;
- g_assert (cattr->ctor->method);
- ainfo->attrs [index].data = saved;
- ainfo->attrs [index].data_size = mono_array_length (cattr->data);
- index ++;
- }
- }
- g_assert (index == num_attrs && count == num_attrs + not_visible);
-
- return ainfo;
+ mono_event->klass = klass;
+ mono_event->event = event;
+ res = (MonoReflectionEvent*)mono_event;
+ CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
}
-#ifndef DISABLE_REFLECTION_EMIT
-/*
- * LOCKING: Acquires the loader lock.
+/**
+ * mono_get_reflection_missing_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.Reflection.Missing.Value singleton object
+ * (of type System.Reflection.Missing).
+ *
+ * Used as the value for ParameterInfo.DefaultValue when Optional
+ * is present
*/
-static void
-mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
+static MonoObject *
+mono_get_reflection_missing_object (MonoDomain *domain)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoCustomAttrInfo *ainfo, *tmp;
-
- if (!cattrs || !mono_array_length (cattrs))
- return;
-
- ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
-
- mono_loader_lock ();
- tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
- if (tmp)
- mono_custom_attrs_free (tmp);
- mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
- mono_loader_unlock ();
-
+ MonoError error;
+ MonoObject *obj;
+ static MonoClassField *missing_value_field = NULL;
+
+ if (!missing_value_field) {
+ MonoClass *missing_klass;
+ missing_klass = mono_class_get_missing_class ();
+ mono_class_init (missing_klass);
+ missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
+ g_assert (missing_value_field);
+ }
+ obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
+ mono_error_assert_ok (&error);
+ return obj;
}
-#endif
-void
-mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
+static MonoObject*
+get_dbnull (MonoDomain *domain, MonoObject **dbnull)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ if (!*dbnull)
+ *dbnull = mono_get_dbnull_object (domain);
+ return *dbnull;
+}
- if (ainfo && !ainfo->cached)
- g_free (ainfo);
+static MonoObject*
+get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
+{
+ if (!*reflection_missing)
+ *reflection_missing = mono_get_reflection_missing_object (domain);
+ return *reflection_missing;
}
/*
- * idx is the table index of the object
- * type is one of MONO_CUSTOM_ATTR_*
+ * mono_param_get_objects:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.ParameterInfo array object representing the parameters
+ * in the method @method.
*/
-static gboolean
-mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
+MonoArray*
+mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ static MonoClass *System_Reflection_ParameterInfo;
+ static MonoClass *System_Reflection_ParameterInfo_array;
+ MonoArray *res = NULL;
+ MonoReflectionMethod *member = NULL;
+ MonoReflectionParameter *param = NULL;
+ char **names = NULL, **blobs = NULL;
+ guint32 *types = NULL;
+ MonoType *type = NULL;
+ MonoObject *dbnull = NULL;
+ MonoObject *missing = NULL;
+ MonoMarshalSpec **mspecs = NULL;
+ MonoMethodSignature *sig = NULL;
+ MonoVTable *pinfo_vtable;
+ MonoReflectionType *rt;
+ int i;
- MonoDynamicTable *table;
- MonoReflectionCustomAttr *cattr;
- guint32 *values;
- guint32 count, i, token;
- char blob_size [6];
- char *p = blob_size;
-
mono_error_init (error);
+
+ if (!System_Reflection_ParameterInfo_array) {
+ MonoClass *klass;
- /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
- if (!cattrs)
- return TRUE;
- count = mono_array_length (cattrs);
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- table->rows += count;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= type;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- values [MONO_CUSTOM_ATTR_PARENT] = idx;
- token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
- if (!mono_error_ok (error)) goto fail;
- type = mono_metadata_token_index (token);
- type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
- switch (mono_metadata_token_table (token)) {
- case MONO_TABLE_METHOD:
- type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- /*
- * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
- * method, not the one returned by mono_image_create_token ().
- */
- mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
- break;
- case MONO_TABLE_MEMBERREF:
- type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
- break;
- default:
- g_warning ("got wrong token in custom attr");
- continue;
- }
- values [MONO_CUSTOM_ATTR_TYPE] = type;
- p = blob_size;
- mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
- values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
- mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
- values += MONO_CUSTOM_ATTR_SIZE;
- ++table->next_idx;
- }
-
- return TRUE;
-
-fail:
- return FALSE;
-}
+ klass = mono_class_get_mono_parameter_info_class ();
-static void
-mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ mono_memory_barrier ();
+ System_Reflection_ParameterInfo = klass;
- MonoDynamicTable *table;
- guint32 *values;
- guint32 count, i, idx;
- MonoReflectionPermissionSet *perm;
+
+ klass = mono_array_class_get (klass, 1);
+ mono_memory_barrier ();
+ System_Reflection_ParameterInfo_array = klass;
+ }
- if (!permissions)
- return;
+ sig = mono_method_signature_checked (method, error);
+ if (!mono_error_ok (error))
+ goto leave;
- count = mono_array_length (permissions);
- table = &assembly->tables [MONO_TABLE_DECLSECURITY];
- table->rows += count;
- alloc_table (table, table->rows);
+ if (!sig->param_count) {
+ res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
+ if (!res)
+ goto leave;
- for (i = 0; i < mono_array_length (permissions); ++i) {
- perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
+ return res;
+ }
- values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
+ /* Note: the cache is based on the address of the signature into the method
+ * since we already cache MethodInfos with the method as keys.
+ */
+ CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
- idx = mono_metadata_token_index (parent_token);
- idx <<= MONO_HAS_DECL_SECURITY_BITS;
- switch (mono_metadata_token_table (parent_token)) {
- case MONO_TABLE_TYPEDEF:
- idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
- break;
- case MONO_TABLE_METHOD:
- idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
- break;
- case MONO_TABLE_ASSEMBLY:
- idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
- break;
- default:
- g_assert_not_reached ();
- }
-
- values [MONO_DECL_SECURITY_ACTION] = perm->action;
- values [MONO_DECL_SECURITY_PARENT] = idx;
- values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
+ member = mono_method_get_object_checked (domain, method, refclass, error);
+ if (!member)
+ goto leave;
+ names = g_new (char *, sig->param_count);
+ mono_method_get_param_names (method, (const char **) names);
- ++table->next_idx;
- }
-}
+ mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
+ mono_method_get_marshal_info (method, mspecs);
-/*
- * Fill in the MethodDef and ParamDef tables for a method.
- * This is used for both normal methods and constructors.
- */
-static gboolean
-mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
+ if (!res)
+ goto leave;
- MonoDynamicTable *table;
- guint32 *values;
- guint i, count;
+ pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
+ for (i = 0; i < sig->param_count; ++i) {
+ param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
+ if (!param)
+ goto leave;
- mono_error_init (error);
+ rt = mono_type_get_object_checked (domain, sig->params [i], error);
+ if (!rt)
+ goto leave;
- /* room in this table is already allocated */
- table = &assembly->tables [MONO_TABLE_METHOD];
- *mb->table_idx = table->next_idx ++;
- g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
- values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
- values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
- return_val_if_nok (error, FALSE);
- values [MONO_METHOD_FLAGS] = mb->attrs;
- values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
- values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
- return_val_if_nok (error, FALSE);
- values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
- return_val_if_nok (error, FALSE);
+ MONO_OBJECT_SETREF (param, ClassImpl, rt);
- table = &assembly->tables [MONO_TABLE_PARAM];
- values [MONO_METHOD_PARAMLIST] = table->next_idx;
+ MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
- mono_image_add_decl_security (assembly,
- mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
+ MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
- if (mb->pinfo) {
- MonoDynamicTable *mtable;
- guint32 *mvalues;
-
- mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
-
- count = 0;
- for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
- if (mono_array_get (mb->pinfo, gpointer, i))
- count++;
- }
- table->rows += count;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_PARAM_SIZE;
- for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
- values [MONO_PARAM_FLAGS] = pb->attrs;
- values [MONO_PARAM_SEQUENCE] = i;
- if (pb->name != NULL) {
- values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
- return_val_if_nok (error, FALSE);
- } else {
- values [MONO_PARAM_NAME] = 0;
- }
- values += MONO_PARAM_SIZE;
- if (pb->marshal_info) {
- mtable->rows++;
- alloc_table (mtable, mtable->rows);
- mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
- mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
- mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
- return_val_if_nok (error, FALSE);
- }
- pb->table_idx = table->next_idx++;
- if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
- guint32 field_type = 0;
- mtable = &assembly->tables [MONO_TABLE_CONSTANT];
- mtable->rows ++;
- alloc_table (mtable, mtable->rows);
- mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
- mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
- mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
- mvalues [MONO_CONSTANT_TYPE] = field_type;
- mvalues [MONO_CONSTANT_PADDING] = 0;
- }
- }
- }
- }
+ param->PositionImpl = i;
+ param->AttrsImpl = sig->params [i]->attrs;
- return TRUE;
-}
+ if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
+ if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+ else
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
+ } else {
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ if (!blobs) {
+ blobs = g_new0 (char *, sig->param_count);
+ types = g_new0 (guint32, sig->param_count);
+ get_default_param_value_blobs (method, blobs, types);
+ }
- mono_error_init (error);
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+ /* Build MonoType for the type from the Constant Table */
+ if (!type)
+ type = g_new0 (MonoType, 1);
+ type->type = (MonoTypeEnum)types [i];
+ type->data.klass = NULL;
+ if (types [i] == MONO_TYPE_CLASS)
+ type->data.klass = mono_defaults.object_class;
+ else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
+ /* For enums, types [i] contains the base type */
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
- return_val_if_nok (error, FALSE);
- rmb->parameters = mb->parameters;
- rmb->generic_params = mb->generic_params;
- rmb->generic_container = mb->generic_container;
- rmb->opt_types = NULL;
- rmb->pinfo = mb->pinfo;
- rmb->attrs = mb->attrs;
- rmb->iattrs = mb->iattrs;
- rmb->call_conv = mb->call_conv;
- rmb->code = mb->code;
- rmb->type = mb->type;
- rmb->name = mb->name;
- rmb->table_idx = &mb->table_idx;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = FALSE;
- rmb->return_modreq = mb->return_modreq;
- rmb->return_modopt = mb->return_modopt;
- rmb->param_modreq = mb->param_modreq;
- rmb->param_modopt = mb->param_modopt;
- rmb->permissions = mb->permissions;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-
- if (mb->dll) {
- rmb->charset = mb->charset;
- rmb->extra_flags = mb->extra_flags;
- rmb->native_cc = mb->native_cc;
- rmb->dllentry = mb->dllentry;
- rmb->dll = mb->dll;
- }
+ type->type = MONO_TYPE_VALUETYPE;
+ type->data.klass = mono_class_from_mono_type (sig->params [i]);
+ } else
+ type->data.klass = mono_class_from_mono_type (type);
- return TRUE;
-}
+ MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
-static gboolean
-reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
+ if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
+ if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+ else
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
+ }
+
+ }
- const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+ if (mspecs [i + 1]) {
+ MonoReflectionMarshalAsAttribute* mobj;
+ mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
+ if (!mobj)
+ goto leave;
+ MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
+ }
+
+ mono_array_setref (res, i, param);
+ }
- mono_error_init (error);
+leave:
+ g_free (names);
+ g_free (blobs);
+ g_free (types);
+ g_free (type);
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+ if (sig) {
+ for (i = sig->param_count; i >= 0; i--) {
+ if (mspecs [i])
+ mono_metadata_free_marshal_spec (mspecs [i]);
+ }
+ }
+ g_free (mspecs);
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
- return_val_if_nok (error, FALSE);
- rmb->parameters = mb->parameters;
- rmb->generic_params = NULL;
- rmb->generic_container = NULL;
- rmb->opt_types = NULL;
- rmb->pinfo = mb->pinfo;
- rmb->attrs = mb->attrs;
- rmb->iattrs = mb->iattrs;
- rmb->call_conv = mb->call_conv;
- rmb->code = NULL;
- rmb->type = mb->type;
- rmb->name = mono_string_new (mono_domain_get (), name);
- rmb->table_idx = &mb->table_idx;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = FALSE;
- rmb->return_modreq = NULL;
- rmb->return_modopt = NULL;
- rmb->param_modreq = mb->param_modreq;
- rmb->param_modopt = mb->param_modopt;
- rmb->permissions = mb->permissions;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-
- return TRUE;
+ if (!is_ok (error))
+ return NULL;
+
+ CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
}
-static void
-reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
+MonoArray*
+mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
-
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mb->rtype;
- rmb->parameters = mb->parameters;
- rmb->generic_params = NULL;
- rmb->generic_container = NULL;
- rmb->opt_types = NULL;
- rmb->pinfo = NULL;
- rmb->attrs = mb->attrs;
- rmb->iattrs = 0;
- rmb->call_conv = mb->call_conv;
- rmb->code = NULL;
- rmb->type = (MonoObject *) mb->owner;
- rmb->name = mb->name;
- rmb->table_idx = NULL;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = mb->skip_visibility;
- rmb->return_modreq = NULL;
- rmb->return_modopt = NULL;
- rmb->param_modreq = NULL;
- rmb->param_modopt = NULL;
- rmb->permissions = NULL;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-}
-#endif
+ MonoError error;
+ MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
-static gboolean
-mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
+/*
+ * mono_method_body_get_object:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.MethodBody object representing the method @method.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
- MonoDynamicTable *table;
- guint32 *values;
- guint32 tok;
- MonoReflectionMethod *m;
+/**
+ * mono_method_body_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @error: set on error
+ *
+ * Return an System.Reflection.MethodBody object representing the
+ * method @method. On failure, returns NULL and sets @error.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
+{
+ MonoReflectionMethodBody *ret;
+ MonoMethodHeader *header;
+ MonoImage *image;
+ MonoReflectionType *rt;
+ guint32 method_rva, local_var_sig_token;
+ char *ptr;
+ unsigned char format, flags;
int i;
mono_error_init (error);
- if (!mb->override_methods)
- return TRUE;
+ /* for compatibility with .net */
+ if (method_is_dynamic (method)) {
+ mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
+ return NULL;
+ }
- for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
- m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
+ CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
- table = &assembly->tables [MONO_TABLE_METHODIMPL];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_METHODIMPL_SIZE;
- values [MONO_METHODIMPL_CLASS] = tb->table_idx;
- values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+ (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
+ return NULL;
- tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
- return_val_if_nok (error, FALSE);
+ image = method->klass->image;
+ header = mono_method_get_header_checked (method, error);
+ return_val_if_nok (error, NULL);
- switch (mono_metadata_token_table (tok)) {
- case MONO_TABLE_MEMBERREF:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
+ if (!image_is_dynamic (image)) {
+ /* Obtain local vars signature token */
+ method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
+ ptr = mono_image_rva_map (image, method_rva);
+ flags = *(const unsigned char *) ptr;
+ format = flags & METHOD_HEADER_FORMAT_MASK;
+ switch (format){
+ case METHOD_HEADER_TINY_FORMAT:
+ local_var_sig_token = 0;
break;
- case MONO_TABLE_METHOD:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
+ case METHOD_HEADER_FAT_FORMAT:
+ ptr += 2;
+ ptr += 2;
+ ptr += 4;
+ local_var_sig_token = read32 (ptr);
break;
default:
g_assert_not_reached ();
}
- values [MONO_METHODIMPL_DECLARATION] = tok;
- }
+ } else
+ local_var_sig_token = 0; //FIXME
- return TRUE;
-}
+ ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
+ if (!is_ok (error))
+ goto fail;
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ ret->init_locals = header->init_locals;
+ ret->max_stack = header->max_stack;
+ ret->local_var_sig_token = local_var_sig_token;
+ MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_OBJECT_SETREF (ret, il, il_arr);
+ memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
- MonoDynamicTable *table;
- guint32 *values;
- ReflectionMethodBuilder rmb;
- int i;
+ /* Locals */
+ MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_OBJECT_SETREF (ret, locals, locals_arr);
+ for (i = 0; i < header->num_locals; ++i) {
+ MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
+ if (!is_ok (error))
+ goto fail;
- mono_error_init (error);
+ rt = mono_type_get_object_checked (domain, header->locals [i], error);
+ if (!is_ok (error))
+ goto fail;
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
- !mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
+ MONO_OBJECT_SETREF (info, local_type, rt);
- mb->table_idx = *rmb.table_idx;
-
- if (mb->dll) { /* It's a P/Invoke method */
- guint32 moduleref;
- /* map CharSet values to on-disk values */
- int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
- int extra_flags = mb->extra_flags;
- table = &assembly->tables [MONO_TABLE_IMPLMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_IMPLMAP_SIZE;
-
- values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
- values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
- if (mb->dllentry) {
- values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
- return_val_if_nok (error, FALSE);
- } else {
- values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
- return_val_if_nok (error, FALSE);
- }
- moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
- return_val_if_nok (error, FALSE);
- if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
- table = &assembly->tables [MONO_TABLE_MODULEREF];
- table->rows ++;
- alloc_table (table, table->rows);
- table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
- values [MONO_IMPLMAP_SCOPE] = table->rows;
- }
+ info->is_pinned = header->locals [i]->pinned;
+ info->local_index = i;
+ mono_array_setref (ret->locals, i, info);
}
- if (mb->generic_params) {
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table->rows += mono_array_length (mb->generic_params);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
- guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
+ /* Exceptions */
+ MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
+ for (i = 0; i < header->num_clauses; ++i) {
+ MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
+ if (!is_ok (error))
+ goto fail;
+ MonoExceptionClause *clause = &header->clauses [i];
- mono_image_get_generic_param_info (
- (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- ReflectionMethodBuilder rmb;
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return FALSE;
-
- if (!mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
-
- mb->table_idx = *rmb.table_idx;
-
- return TRUE;
-}
-#endif
-
-static char*
-type_get_fully_qualified_name (MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
-}
-
-static char*
-type_get_qualified_name (MonoType *type, MonoAssembly *ass)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ info->flags = clause->flags;
+ info->try_offset = clause->try_offset;
+ info->try_length = clause->try_len;
+ info->handler_offset = clause->handler_offset;
+ info->handler_length = clause->handler_len;
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
+ info->filter_offset = clause->data.filter_offset;
+ else if (clause->data.catch_class) {
+ rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
+ if (!is_ok (error))
+ goto fail;
- MonoClass *klass;
- MonoAssembly *ta;
+ MONO_OBJECT_SETREF (info, catch_type, rt);
+ }
- klass = mono_class_from_mono_type (type);
- if (!klass)
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
- ta = klass->image->assembly;
- if (assembly_is_dynamic (ta) || (ta == ass)) {
- if (klass->generic_class || klass->generic_container)
- /* For generic type definitions, we want T, while REFLECTION returns T<K> */
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
- else
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+ mono_array_setref (ret->clauses, i, info);
}
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+ mono_metadata_free_mh (header);
+ CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
+ return ret;
+
+fail:
+ mono_metadata_free_mh (header);
+ return NULL;
}
-#ifndef DISABLE_REFLECTION_EMIT
-/*field_image is the image to which the eventual custom mods have been encoded against*/
-static guint32
-fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
+/**
+ * mono_get_dbnull_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.DBNull.Value singleton object
+ *
+ * Used as the value for ParameterInfo.DefaultValue
+ */
+MonoObject *
+mono_get_dbnull_object (MonoDomain *domain)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- SigBuffer buf;
- guint32 idx, i, token;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
+ MonoError error;
+ MonoObject *obj;
+ static MonoClassField *dbnull_value_field = NULL;
- sigbuffer_add_value (&buf, 0x06);
- /* encode custom attributes before the type */
- if (type->num_mods) {
- for (i = 0; i < type->num_mods; ++i) {
- if (field_image) {
- MonoError error;
- MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
-
- token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
- } else {
- token = type->modifiers [i].token;
- }
-
- if (type->modifiers [i].required)
- sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
- else
- sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
-
- sigbuffer_add_value (&buf, token);
- }
+ if (!dbnull_value_field) {
+ MonoClass *dbnull_klass;
+ dbnull_klass = mono_class_get_dbnull_class ();
+ dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
+ g_assert (dbnull_value_field);
}
- encode_type (assembly, type, &buf);
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
+ obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
+ mono_error_assert_ok (&error);
+ return obj;
}
-#endif
-static guint32
-field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
+static void
+get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- SigBuffer buf;
- guint32 idx;
- guint32 typespec = 0;
- MonoType *type;
- MonoClass *klass;
-
- init_type_builder_generics (fb->type, error);
- return_val_if_nok (error, 0);
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
+ guint32 param_index, i, lastp, crow = 0;
+ guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
+ gint32 idx;
- sigbuffer_init (&buf, 32);
-
- sigbuffer_add_value (&buf, 0x06);
- encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
- if (!is_ok (error))
- goto fail;
- /* encode custom attributes before the type */
+ MonoClass *klass = method->klass;
+ MonoImage *image = klass->image;
+ MonoMethodSignature *methodsig = mono_method_signature (method);
- if (klass->generic_container)
- typespec = create_typespec (assembly, type);
+ MonoTableInfo *constt;
+ MonoTableInfo *methodt;
+ MonoTableInfo *paramt;
- if (typespec) {
- MonoGenericClass *gclass;
- gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
- encode_generic_class (assembly, gclass, &buf);
- } else {
- encode_type (assembly, type, &buf);
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
+ if (!methodsig->param_count)
+ return;
-static guint32
-encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ mono_class_init (klass);
- char blob_size [64];
- char *b = blob_size;
- char *box_val;
- char* buf;
- guint32 idx = 0, len = 0, dummy = 0;
-
- buf = (char *)g_malloc (64);
- if (!val) {
- *ret_type = MONO_TYPE_CLASS;
- len = 4;
- box_val = (char*)&dummy;
- } else {
- box_val = ((char*)val) + sizeof (MonoObject);
- *ret_type = val->vtable->klass->byval_arg.type;
- }
-handle_enum:
- switch (*ret_type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- len = 1;
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- len = 2;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- len = 4;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- len = 8;
- break;
- case MONO_TYPE_R8:
- len = 8;
- break;
- case MONO_TYPE_VALUETYPE: {
- MonoClass *klass = val->vtable->klass;
-
- if (klass->enumtype) {
- *ret_type = mono_class_enum_basetype (klass)->type;
- goto handle_enum;
- } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
- len = 8;
- } else
- g_error ("we can't encode valuetypes, we should have never reached this line");
- break;
- }
- case MONO_TYPE_CLASS:
- break;
- case MONO_TYPE_STRING: {
- MonoString *str = (MonoString*)val;
- /* there is no signature */
- len = str->length * 2;
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
-
- swap_with_size (swapped, p, 2, mono_string_length (str));
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
- g_free (swapped);
+ if (image_is_dynamic (klass->image)) {
+ MonoReflectionMethodAux *aux;
+ if (method->is_inflated)
+ method = ((MonoMethodInflated*)method)->declaring;
+ aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+ if (aux && aux->param_defaults) {
+ memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
+ memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
}
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
-#endif
-
- g_free (buf);
- return idx;
- }
- case MONO_TYPE_GENERICINST:
- *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
- goto handle_enum;
- default:
- g_error ("we don't encode constant type 0x%02x yet", *ret_type);
+ return;
}
- /* there is no signature */
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- swap_with_size (blob_size, box_val, len, 1);
- mono_image_add_stream_data (&assembly->blob, blob_size, len);
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
-#endif
-
- g_free (buf);
- return idx;
-}
-
-static guint32
-encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ methodt = &klass->image->tables [MONO_TABLE_METHOD];
+ paramt = &klass->image->tables [MONO_TABLE_PARAM];
+ constt = &image->tables [MONO_TABLE_CONSTANT];
- mono_error_init (error);
+ idx = mono_method_get_index (method) - 1;
+ g_assert (idx != -1);
- char *str;
- SigBuffer buf;
- guint32 idx, len;
+ param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
+ if (idx + 1 < methodt->rows)
+ lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
+ else
+ lastp = paramt->rows + 1;
- sigbuffer_init (&buf, 32);
+ for (i = param_index; i < lastp; ++i) {
+ guint32 paramseq;
- sigbuffer_add_value (&buf, minfo->type);
+ mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
+ paramseq = param_cols [MONO_PARAM_SEQUENCE];
- switch (minfo->type) {
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- sigbuffer_add_value (&buf, minfo->count);
- break;
- case MONO_NATIVE_LPARRAY:
- if (minfo->eltype || minfo->has_size) {
- sigbuffer_add_value (&buf, minfo->eltype);
- if (minfo->has_size) {
- sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
- sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
+ if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
+ continue;
- /* LAMESPEC: ElemMult is undocumented */
- sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
- }
- }
- break;
- case MONO_NATIVE_SAFEARRAY:
- if (minfo->eltype)
- sigbuffer_add_value (&buf, minfo->eltype);
- break;
- case MONO_NATIVE_CUSTOM:
- if (minfo->guid) {
- str = mono_string_to_utf8_checked (minfo->guid, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- sigbuffer_add_value (&buf, 0);
- }
- /* native type name */
- sigbuffer_add_value (&buf, 0);
- /* custom marshaler type name */
- if (minfo->marshaltype || minfo->marshaltyperef) {
- if (minfo->marshaltyperef) {
- MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- str = type_get_fully_qualified_name (marshaltype);
- } else {
- str = mono_string_to_utf8_checked (minfo->marshaltype, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- /* FIXME: Actually a bug, since this field is required. Punting for now ... */
- sigbuffer_add_value (&buf, 0);
- }
- if (minfo->mcookie) {
- str = mono_string_to_utf8_checked (minfo->mcookie, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- sigbuffer_add_value (&buf, 0);
+ crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
+ if (!crow) {
+ continue;
}
- break;
- default:
- break;
+
+ mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
+ blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
+ types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
}
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-
-static void
-mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
- MonoDynamicTable *table;
- guint32 *values;
-
- /* maybe this fixup should be done in the C# code */
- if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
- fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
- table = &assembly->tables [MONO_TABLE_FIELD];
- fb->table_idx = table->next_idx ++;
- g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
- values = table->values + fb->table_idx * MONO_FIELD_SIZE;
- values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
- return_if_nok (error);
- values [MONO_FIELD_FLAGS] = fb->attrs;
- values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
- return_if_nok (error);
-
-
- if (fb->offset != -1) {
- table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
- values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
- values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
- }
- if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
- MonoTypeEnum field_type = (MonoTypeEnum)0;
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CONSTANT_SIZE;
- values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
- values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
- values [MONO_CONSTANT_TYPE] = field_type;
- values [MONO_CONSTANT_PADDING] = 0;
- }
- if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
- guint32 rva_idx;
- table = &assembly->tables [MONO_TABLE_FIELDRVA];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
- values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
- /*
- * We store it in the code section because it's simpler for now.
- */
- if (fb->rva_data) {
- if (mono_array_length (fb->rva_data) >= 10)
- stream_data_align (&assembly->code);
- rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
- } else
- rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
- values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
- }
- if (fb->marshal_info) {
- table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
- values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
- values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
- return_if_nok (error);
- }
+ return;
}
-static guint32
-property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
+MonoObject *
+mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ void *retval;
+ MonoClass *klass;
+ MonoObject *object;
+ MonoType *basetype = type;
mono_error_init (error);
- SigBuffer buf;
- guint32 nparams = 0;
- MonoReflectionMethodBuilder *mb = fb->get_method;
- MonoReflectionMethodBuilder *smb = fb->set_method;
- guint32 idx, i;
-
- if (mb && mb->parameters)
- nparams = mono_array_length (mb->parameters);
- if (!mb && smb && smb->parameters)
- nparams = mono_array_length (smb->parameters) - 1;
- sigbuffer_init (&buf, 32);
- if (fb->call_conv & 0x20)
- sigbuffer_add_byte (&buf, 0x28);
- else
- sigbuffer_add_byte (&buf, 0x08);
- sigbuffer_add_value (&buf, nparams);
- if (mb) {
- encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
- if (!is_ok (error))
- goto fail;
- for (i = 0; i < nparams; ++i) {
- MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
- }
- } else if (smb && smb->parameters) {
- /* the property type is the last param */
- encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
- if (!is_ok (error))
- goto fail;
-
- for (i = 0; i < nparams; ++i) {
- MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
- }
+ if (!blob)
+ return NULL;
+
+ klass = mono_class_from_mono_type (type);
+ if (klass->valuetype) {
+ object = mono_object_new_checked (domain, klass, error);
+ return_val_if_nok (error, NULL);
+ retval = ((gchar *) object + sizeof (MonoObject));
+ if (klass->enumtype)
+ basetype = mono_class_enum_basetype (klass);
} else {
- encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
- if (!is_ok (error))
- goto fail;
+ retval = &object;
}
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
+
+ if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
+ return object;
+ else
+ return NULL;
}
-static void
-mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
+static int
+assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
+ int found_sep;
+ char *s;
+ gboolean quoted = FALSE;
- MonoDynamicTable *table;
- guint32 *values;
- guint num_methods = 0;
- guint32 semaidx;
+ memset (assembly, 0, sizeof (MonoAssemblyName));
+ assembly->culture = "";
+ memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
- /*
- * we need to set things in the following tables:
- * PROPERTYMAP (info already filled in _get_type_info ())
- * PROPERTY (rows already preallocated in _get_type_info ())
- * METHOD (method info already done with the generic method code)
- * METHODSEMANTICS
- * CONSTANT
- */
- table = &assembly->tables [MONO_TABLE_PROPERTY];
- pb->table_idx = table->next_idx ++;
- values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
- values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
- return_if_nok (error);
- values [MONO_PROPERTY_FLAGS] = pb->attrs;
- values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
- return_if_nok (error);
-
-
- /* FIXME: we still don't handle 'other' methods */
- if (pb->get_method) num_methods ++;
- if (pb->set_method) num_methods ++;
-
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- table->rows += num_methods;
- alloc_table (table, table->rows);
-
- if (pb->get_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
- values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
- }
- if (pb->set_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
- values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
+ if (*p == '"') {
+ quoted = TRUE;
+ p++;
}
- if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
- MonoTypeEnum field_type = (MonoTypeEnum)0;
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CONSTANT_SIZE;
- values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
- values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
- values [MONO_CONSTANT_TYPE] = field_type;
- values [MONO_CONSTANT_PADDING] = 0;
- }
-}
-
-static void
-mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint num_methods = 0;
- guint32 semaidx;
-
- /*
- * we need to set things in the following tables:
- * EVENTMAP (info already filled in _get_type_info ())
- * EVENT (rows already preallocated in _get_type_info ())
- * METHOD (method info already done with the generic method code)
- * METHODSEMANTICS
- */
- table = &assembly->tables [MONO_TABLE_EVENT];
- eb->table_idx = table->next_idx ++;
- values = table->values + eb->table_idx * MONO_EVENT_SIZE;
- values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
- return_if_nok (error);
- values [MONO_EVENT_FLAGS] = eb->attrs;
- MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
- return_if_nok (error);
- values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
-
- /*
- * FIXME: we still don't handle 'other' methods
- */
- if (eb->add_method) num_methods ++;
- if (eb->remove_method) num_methods ++;
- if (eb->raise_method) num_methods ++;
-
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- table->rows += num_methods;
- alloc_table (table, table->rows);
-
- if (eb->add_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
- values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
- }
- if (eb->remove_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
- values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
- }
- if (eb->raise_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
- values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
- }
-}
-
-static void
-encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- MonoDynamicTable *table;
- guint32 num_constraints, i;
- guint32 *values;
- guint32 table_idx;
-
- table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
- num_constraints = gparam->iface_constraints ?
- mono_array_length (gparam->iface_constraints) : 0;
- table->rows += num_constraints;
- if (gparam->base_type)
- table->rows++;
- alloc_table (table, table->rows);
-
- if (gparam->base_type) {
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
-
- MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
- return_if_nok (error);
- values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
- values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
- }
-
- for (i = 0; i < num_constraints; i++) {
- MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
- gparam->iface_constraints, gpointer, i);
-
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
-
- MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
- return_if_nok (error);
-
- values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
- values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
- }
-}
-
-static void
-mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- GenericParamTableEntry *entry;
-
- /*
- * The GenericParam table must be sorted according to the `owner' field.
- * We need to do this sorting prior to writing the GenericParamConstraint
- * table, since we have to use the final GenericParam table indices there
- * and they must also be sorted.
- */
-
- entry = g_new0 (GenericParamTableEntry, 1);
- entry->owner = owner;
- /* FIXME: track where gen_params should be freed and remove the GC root as well */
- MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
- entry->gparam = gparam;
-
- g_ptr_array_add (assembly->gen_params, entry);
-}
-
-static gboolean
-write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- MonoGenericParam *param;
- guint32 *values;
- guint32 table_idx;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
-
- MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
- return_val_if_nok (error, FALSE);
-
- param = gparam_type->data.generic_param;
-
- values [MONO_GENERICPARAM_OWNER] = entry->owner;
- values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
- values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
- values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
-
- if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
- return FALSE;
-
- encode_constraints (entry->gparam, table_idx, assembly, error);
- return_val_if_nok (error, FALSE);
-
- return TRUE;
-}
-
-static guint32
-resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 token;
- guint32 *values;
- guint32 cols [MONO_ASSEMBLY_SIZE];
- const char *pubkey;
- guint32 publen;
-
- if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
- return token;
-
- if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
- table = &assembly->tables [MONO_TABLE_MODULEREF];
- token = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + token * MONO_MODULEREF_SIZE;
- values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
-
- token <<= MONO_RESOLUTION_SCOPE_BITS;
- token |= MONO_RESOLUTION_SCOPE_MODULEREF;
- g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
-
- return token;
- }
-
- if (assembly_is_dynamic (image->assembly))
- /* FIXME: */
- memset (cols, 0, sizeof (cols));
- else {
- /* image->assembly->image is the manifest module */
- image = image->assembly->image;
- mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
- }
-
- table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
- token = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + token * MONO_ASSEMBLYREF_SIZE;
- values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
- values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
- values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
- values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
- values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
- values [MONO_ASSEMBLYREF_FLAGS] = 0;
- values [MONO_ASSEMBLYREF_CULTURE] = 0;
- values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
-
- if (strcmp ("", image->assembly->aname.culture)) {
- values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
- image->assembly->aname.culture);
- }
-
- if ((pubkey = mono_image_get_public_key (image, &publen))) {
- guchar pubtoken [9];
- pubtoken [0] = 8;
- mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
- values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
- } else {
- values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
- }
- token <<= MONO_RESOLUTION_SCOPE_BITS;
- token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
- g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-create_typespec (MonoDynamicImage *assembly, MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token;
- SigBuffer buf;
-
- if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
- return token;
-
- sigbuffer_init (&buf, 32);
- switch (type->type) {
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_PTR:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- case MONO_TYPE_GENERICINST:
- encode_type (assembly, type, &buf);
- break;
- case MONO_TYPE_CLASS:
- case MONO_TYPE_VALUETYPE: {
- MonoClass *k = mono_class_from_mono_type (type);
- if (!k || !k->generic_container) {
- sigbuffer_free (&buf);
- return 0;
- }
- encode_type (assembly, type, &buf);
- break;
- }
- default:
- sigbuffer_free (&buf);
- return 0;
- }
-
- table = &assembly->tables [MONO_TABLE_TYPESPEC];
- if (assembly->save) {
- token = sigbuffer_add_to_blob_cached (assembly, &buf);
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
- }
- sigbuffer_free (&buf);
-
- token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
- g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- return token;
-}
-
-static guint32
-mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, scope, enclosing;
- MonoClass *klass;
-
- /* if the type requires a typespec, we must try that first*/
- if (try_typespec && (token = create_typespec (assembly, type)))
- return token;
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
- if (token)
- return token;
- klass = mono_class_from_mono_type (type);
- if (!klass)
- klass = mono_class_from_mono_type (type);
-
- /*
- * If it's in the same module and not a generic type parameter:
- */
- if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
- (type->type != MONO_TYPE_MVAR)) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
- register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
- return token;
- }
-
- if (klass->nested_in) {
- enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
- /* get the typeref idx of the enclosing type */
- enclosing >>= MONO_TYPEDEFORREF_BITS;
- scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
- } else {
- scope = resolution_scope_from_image (assembly, klass->image);
- }
- table = &assembly->tables [MONO_TABLE_TYPEREF];
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
- values [MONO_TYPEREF_SCOPE] = scope;
- values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
- }
- token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
- g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
- return token;
-}
-
-/*
- * Despite the name, we handle also TypeSpec (with the above helper).
- */
-static guint32
-mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
-{
- return mono_image_typedef_or_ref_full (assembly, type, TRUE);
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, pclass;
-
- switch (parent & MONO_TYPEDEFORREF_MASK) {
- case MONO_TYPEDEFORREF_TYPEREF:
- pclass = MONO_MEMBERREF_PARENT_TYPEREF;
- break;
- case MONO_TYPEDEFORREF_TYPESPEC:
- pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
- break;
- case MONO_TYPEDEFORREF_TYPEDEF:
- pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
- break;
- default:
- g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
- return 0;
- }
- /* extract the index */
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-/*
- * Insert a memberef row into the metadata: the token that point to the memberref
- * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
- * mono_image_get_fieldref_token()).
- * The sig param is an index to an already built signature.
- */
-static guint32
-mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 parent = mono_image_typedef_or_ref (assembly, type);
- return mono_image_add_memberef_row (assembly, parent, name, sig);
-}
-
-
-static guint32
-mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 token;
- MonoMethodSignature *sig;
-
- create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
-
- if (create_typespec) {
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
- if (token)
- return token;
- }
-
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token && !create_typespec)
- return token;
-
- g_assert (!method->is_inflated);
- if (!token) {
- /*
- * A methodref signature can't contain an unmanaged calling convention.
- */
- sig = mono_metadata_signature_dup (mono_method_signature (method));
- if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
- sig->call_convention = MONO_CALL_DEFAULT;
- token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
- method->name, method_encode_signature (assembly, sig));
- g_free (sig);
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
- }
-
- if (create_typespec) {
- MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
- g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
- token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
-
- if (assembly->save) {
- guint32 *values;
-
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = token;
- values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
- /*methodspec and memberef tokens are diferent, */
- g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
- return token;
- }
- return token;
-}
-
-static guint32
-mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
-{
- guint32 token, parent, sig;
- ReflectionMethodBuilder rmb;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
-
- mono_error_init (error);
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token)
- return token;
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
- return 0;
-
- /*
- * A methodref signature can't contain an unmanaged calling convention.
- * Since some flags are encoded as part of call_conv, we need to check against it.
- */
- if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
- rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- if (tb->generic_params) {
- parent = create_generic_typespec (assembly, tb, error);
- return_val_if_nok (error, 0);
- } else {
- MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
- return_val_if_nok (error, 0);
-
- parent = mono_image_typedef_or_ref (assembly, t);
- }
-
- char *name = mono_string_to_utf8_checked (method->name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_add_memberef_row (assembly, parent, name, sig);
- g_free (name);
-
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
-
- return token;
-}
-
-static guint32
-mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
- const gchar *name, guint32 sig)
-{
- MonoDynamicTable *table;
- guint32 token;
- guint32 *values;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = original;
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-static guint32
-encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
-{
- SigBuffer buf;
- int i;
- guint32 nparams = mono_array_length (mb->generic_params);
- guint32 idx;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
-
- sigbuffer_add_value (&buf, 0xa);
- sigbuffer_add_value (&buf, nparams);
-
- for (i = 0; i < nparams; i++) {
- sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
- sigbuffer_add_value (&buf, i);
- }
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-
-static guint32
-mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, mtoken = 0;
-
- mono_error_init (error);
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
- if (token)
- return token;
-
- table = &assembly->tables [MONO_TABLE_METHODSPEC];
-
- mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
-
- switch (mono_metadata_token_table (mtoken)) {
- case MONO_TABLE_MEMBERREF:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
- }
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = mtoken;
- values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
-
- mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
-{
- guint32 token;
-
- mono_error_init (error);
-
- if (mb->generic_params && create_methodspec)
- return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
- if (token)
- return token;
-
- token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
- mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
-{
- guint32 token, parent, sig;
- ReflectionMethodBuilder rmb;
- char *name;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
-
- mono_error_init (error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
- if (token)
- return token;
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return 0;
-
- if (tb->generic_params) {
- parent = create_generic_typespec (assembly, tb, error);
- return_val_if_nok (error, 0);
- } else {
- MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, 0);
- parent = mono_image_typedef_or_ref (assembly, type);
- }
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_add_memberef_row (assembly, parent, name, sig);
-
- g_free (name);
- mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
- return token;
-}
-#endif
-
-static gboolean
-is_field_on_inst (MonoClassField *field)
-{
- return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
-}
-
-/*
- * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
- */
-static MonoType*
-get_field_on_inst_generic_type (MonoClassField *field)
-{
- MonoClass *klass, *gtd;
- MonoDynamicGenericClass *dgclass;
- int field_index;
-
- g_assert (is_field_on_inst (field));
-
- dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
-
- if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
- field_index = field - dgclass->fields;
- return dgclass->field_generic_types [field_index];
- }
-
- klass = field->parent;
- gtd = klass->generic_class->container_class;
-
- if (field >= klass->fields && field - klass->fields < klass->field.count) {
- field_index = field - klass->fields;
- return gtd->fields [field_index].type;
- }
-
- g_assert_not_reached ();
- return 0;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
-{
- MonoType *type;
- guint32 token;
-
- g_assert (field);
- g_assert (field->parent);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
- if (token)
- return token;
-
- if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
- int index = field - field->parent->fields;
- type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
- } else {
- if (is_field_on_inst (field))
- type = get_field_on_inst_generic_type (field);
- else
- type = mono_field_get_type (field);
- }
- token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
- mono_field_get_name (field),
- fieldref_encode_signature (assembly, field->parent->image, type));
- mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
-{
- guint32 token;
- MonoClass *klass;
- MonoGenericClass *gclass;
- MonoType *type;
- char *name;
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
- if (token)
- return token;
- if (is_sre_field_builder (mono_object_class (f->fb))) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
- type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- guint32 sig_token = field_encode_signature (assembly, fb, error);
- return_val_if_nok (error, 0);
- name = mono_string_to_utf8_checked (fb->name, error);
- return_val_if_nok (error, 0);
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
- g_free (name);
- } else if (is_sr_mono_field (mono_object_class (f->fb))) {
- guint32 sig;
- MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (f->fb));
- g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
- }
-
- mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
-{
- guint32 sig, token;
- MonoClass *klass;
- MonoGenericClass *gclass;
- MonoType *type;
-
- mono_error_init (error);
-
- /* A ctor cannot be a generic method, so we can ignore create_methodspec */
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
- if (token)
- return token;
-
- if (is_sre_ctor_builder (mono_object_class (c->cb))) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
- ReflectionMethodBuilder rmb;
- char *name;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
- return 0;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
- g_free (name);
- } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
- MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = method_encode_signature (assembly, mono_method_signature (mm));
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (c->cb));
- g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
- }
-
-
- mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
- return token;
-}
-
-static MonoMethod*
-mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
-{
- MonoClass *klass;
- MonoGenericContext tmp_context;
- MonoType **type_argv;
- MonoGenericInst *ginst;
- MonoMethod *method, *inflated;
- int count, i;
-
- mono_error_init (error);
-
- init_type_builder_generics ((MonoObject*)m->inst, error);
- return_val_if_nok (error, NULL);
-
- method = inflate_method (m->inst, (MonoObject*)m->mb, error);
- return_val_if_nok (error, NULL);
-
- klass = method->klass;
-
- if (m->method_args == NULL)
- return method;
-
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- count = mono_array_length (m->method_args);
-
- type_argv = g_new0 (MonoType *, count);
- for (i = 0; i < count; i++) {
- MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
- type_argv [i] = mono_reflection_type_get_handle (garg, error);
- return_val_if_nok (error, NULL);
- }
- ginst = mono_metadata_get_generic_inst (count, type_argv);
- g_free (type_argv);
-
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
- tmp_context.method_inst = ginst;
-
- inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
- mono_error_assert_ok (error);
- return inflated;
-}
-
-static guint32
-mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
-{
- guint32 sig, token = 0;
- MonoType *type;
- MonoClass *klass;
-
- mono_error_init (error);
-
- if (m->method_args) {
- MonoMethod *inflated;
-
- inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
- return_val_if_nok (error, 0);
-
- if (create_methodspec)
- token = mono_image_get_methodspec_token (assembly, inflated);
- else
- token = mono_image_get_inflated_method_token (assembly, inflated);
- return token;
- }
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
- if (token)
- return token;
-
- if (is_sre_method_builder (mono_object_class (m->mb))) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
- MonoGenericClass *gclass;
- ReflectionMethodBuilder rmb;
- char *name;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- return 0;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
- g_free (name);
- } else if (is_sr_mono_method (mono_object_class (m->mb))) {
- MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = method_encode_signature (assembly, mono_method_signature (mm));
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (m->mb));
- g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
- }
-
- mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
-{
- SigBuffer buf;
- int i;
- guint32 nparams = context->method_inst->type_argc;
- guint32 idx;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
- /*
- * FIXME: vararg, explicit_this, differenc call_conv values...
- */
- sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
- sigbuffer_add_value (&buf, nparams);
-
- for (i = 0; i < nparams; i++)
- encode_type (assembly, context->method_inst->type_argv [i], &buf);
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-
-static guint32
-method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, mtoken = 0, sig;
- MonoMethodInflated *imethod;
- MonoMethod *declaring;
-
- table = &assembly->tables [MONO_TABLE_METHODSPEC];
-
- g_assert (method->is_inflated);
- imethod = (MonoMethodInflated *) method;
- declaring = imethod->declaring;
-
- sig = method_encode_signature (assembly, mono_method_signature (declaring));
- mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
-
- if (!mono_method_signature (declaring)->generic_param_count)
- return mtoken;
-
- switch (mono_metadata_token_table (mtoken)) {
- case MONO_TABLE_MEMBERREF:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
- }
-
- sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = mtoken;
- values [MONO_METHODSPEC_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-static guint32
-mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
-{
- MonoMethodInflated *imethod;
- guint32 token;
-
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token)
- return token;
-
- g_assert (method->is_inflated);
- imethod = (MonoMethodInflated *) method;
-
- if (mono_method_signature (imethod->declaring)->generic_param_count) {
- token = method_encode_methodspec (assembly, method);
- } else {
- guint32 sig = method_encode_signature (
- assembly, mono_method_signature (imethod->declaring));
- token = mono_image_get_memberref_token (
- assembly, &method->klass->byval_arg, method->name, sig);
- }
-
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
-{
- MonoMethodInflated *imethod = (MonoMethodInflated *) m;
- guint32 sig, token;
-
- sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
- token = mono_image_get_memberref_token (
- assembly, &m->klass->byval_arg, m->name, sig);
-
- return token;
-}
-
-static guint32
-create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoClass *klass;
- MonoType *type;
- guint32 *values;
- guint32 token;
- SigBuffer buf;
- int count, i;
-
- /*
- * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
- * ie. what we'd normally use as the generic type in a TypeSpec signature.
- * Because of this, we must not insert it into the `typeref' hash table.
- */
- type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, 0);
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
- if (token)
- return token;
-
- sigbuffer_init (&buf, 32);
-
- g_assert (tb->generic_params);
- klass = mono_class_from_mono_type (type);
-
- if (tb->generic_container) {
- if (!mono_reflection_create_generic_class (tb, error))
- goto fail;
- }
-
- sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
- g_assert (klass->generic_container);
- sigbuffer_add_value (&buf, klass->byval_arg.type);
- sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
-
- count = mono_array_length (tb->generic_params);
- sigbuffer_add_value (&buf, count);
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gparam;
-
- gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
- MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
- if (!is_ok (error))
- goto fail;
-
- encode_type (assembly, gparam_type, &buf);
- }
-
- table = &assembly->tables [MONO_TABLE_TYPESPEC];
-
- if (assembly->save) {
- token = sigbuffer_add_to_blob_cached (assembly, &buf);
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
- }
- sigbuffer_free (&buf);
-
- token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
- g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- return token;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
-
-/*
- * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
- */
-static MonoType*
-add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
-{
- int i, count, len, pos;
- MonoType *t;
-
- mono_error_init (error);
-
- count = 0;
- if (modreq)
- count += mono_array_length (modreq);
- if (modopt)
- count += mono_array_length (modopt);
-
- if (count == 0)
- return mono_metadata_type_dup (NULL, type);
-
- len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
- t = (MonoType *)g_malloc (len);
- memcpy (t, type, MONO_SIZEOF_TYPE);
-
- t->num_mods = count;
- pos = 0;
- if (modreq) {
- for (i = 0; i < mono_array_length (modreq); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
- if (!is_ok (error))
- goto fail;
- t->modifiers [pos].required = 1;
- t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
- pos ++;
- }
- }
- if (modopt) {
- for (i = 0; i < mono_array_length (modopt); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
- if (!is_ok (error))
- goto fail;
- t->modifiers [pos].required = 0;
- t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
- pos ++;
- }
- }
-
- return t;
-fail:
- g_free (t);
- return NULL;
-}
-
-static void
-init_type_builder_generics (MonoObject *type, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb;
-
- mono_error_init (error);
-
- if (!is_sre_type_builder(mono_object_class (type)))
- return;
- tb = (MonoReflectionTypeBuilder *)type;
-
- if (tb && tb->generic_container)
- mono_reflection_create_generic_class (tb, error);
-}
-
-static guint32
-mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoType *custom = NULL, *type;
- guint32 *values;
- guint32 token, pclass, parent, sig;
- gchar *name;
-
- mono_error_init (error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
- if (token)
- return token;
-
- MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
- return_val_if_nok (error, 0);
- /* FIXME: is this call necessary? */
- mono_class_from_mono_type (typeb);
-
- /*FIXME this is one more layer of ugliness due how types are created.*/
- init_type_builder_generics (fb->type, error);
- return_val_if_nok (error, 0);
-
- /* fb->type does not include the custom modifiers */
- /* FIXME: We should do this in one place when a fieldbuilder is created */
- type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_val_if_nok (error, 0);
-
- if (fb->modreq || fb->modopt) {
- type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
- return_val_if_nok (error, 0);
- }
-
- sig = fieldref_encode_signature (assembly, NULL, type);
- g_free (custom);
-
- parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
- return_val_if_nok (error, 0);
- g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
-
- pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- name = mono_string_to_utf8_checked (fb->name, error);
- return_val_if_nok (error, 0);
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
- mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
- g_free (name);
- return token;
-}
-
-static guint32
-mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
-{
- SigBuffer buf;
- guint32 nargs;
- guint32 i, idx;
-
- mono_error_init (error);
-
- if (!assembly->save)
- return 0;
-
- /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
- g_assert (helper->type == 2);
-
- if (helper->arguments)
- nargs = mono_array_length (helper->arguments);
- else
- nargs = 0;
-
- sigbuffer_init (&buf, 32);
-
- /* Encode calling convention */
- /* Change Any to Standard */
- if ((helper->call_conv & 0x03) == 0x03)
- helper->call_conv = 0x01;
- /* explicit_this implies has_this */
- if (helper->call_conv & 0x40)
- helper->call_conv &= 0x20;
-
- if (helper->call_conv == 0) { /* Unmanaged */
- idx = helper->unmanaged_call_conv - 1;
- } else {
- /* Managed */
- idx = helper->call_conv & 0x60; /* has_this + explicit_this */
- if (helper->call_conv & 0x02) /* varargs */
- idx += 0x05;
- }
-
- sigbuffer_add_byte (&buf, idx);
- sigbuffer_add_value (&buf, nargs);
- encode_reflection_type (assembly, helper->return_type, &buf, error);
- if (!is_ok (error))
- goto fail;
- for (i = 0; i < nargs; ++i) {
- MonoArray *modreqs = NULL;
- MonoArray *modopts = NULL;
- MonoReflectionType *pt;
-
- if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
- modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
- if (helper->modopts && (i < mono_array_length (helper->modopts)))
- modopts = mono_array_get (helper->modopts, MonoArray*, i);
-
- encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
- if (!is_ok (error))
- goto fail;
- pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
-
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
-
-static guint32
-mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
-{
- guint32 idx;
- MonoDynamicTable *table;
- guint32 *values;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_STANDALONESIG];
- idx = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
-
- values [MONO_STAND_ALONE_SIGNATURE] =
- mono_reflection_encode_sighelper (assembly, helper, error);
- return_val_if_nok (error, 0);
-
- return idx;
-}
-
-static int
-reflection_cc_to_file (int call_conv) {
- switch (call_conv & 0x3) {
- case 0:
- case 1: return MONO_CALL_DEFAULT;
- case 2: return MONO_CALL_VARARG;
- default:
- g_assert_not_reached ();
- }
- return 0;
-}
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-typedef struct {
- MonoType *parent;
- MonoMethodSignature *sig;
- char *name;
- guint32 token;
-} ArrayMethod;
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
-{
- guint32 nparams, i;
- GList *tmp;
- char *name = NULL;
- MonoMethodSignature *sig;
- ArrayMethod *am = NULL;
- MonoType *mtype;
-
- mono_error_init (error);
-
- nparams = mono_array_length (m->parameters);
- sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
- sig->hasthis = 1;
- sig->sentinelpos = -1;
- sig->call_convention = reflection_cc_to_file (m->call_conv);
- sig->param_count = nparams;
- if (m->ret) {
- sig->ret = mono_reflection_type_get_handle (m->ret, error);
- if (!is_ok (error))
- goto fail;
- } else
- sig->ret = &mono_defaults.void_class->byval_arg;
-
- mtype = mono_reflection_type_get_handle (m->parent, error);
- if (!is_ok (error))
- goto fail;
-
- for (i = 0; i < nparams; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
- if (!is_ok (error))
- goto fail;
- }
-
- name = mono_string_to_utf8_checked (m->name, error);
- if (!is_ok (error))
- goto fail;
- for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
- am = (ArrayMethod *)tmp->data;
- if (strcmp (name, am->name) == 0 &&
- mono_metadata_type_equal (am->parent, mtype) &&
- mono_metadata_signature_equal (am->sig, sig)) {
- g_free (name);
- g_free (sig);
- m->table_idx = am->token & 0xffffff;
- return am->token;
- }
- }
- am = g_new0 (ArrayMethod, 1);
- am->name = name;
- am->sig = sig;
- am->parent = mtype;
- am->token = mono_image_get_memberref_token (assembly, am->parent, name,
- method_encode_signature (assembly, sig));
- assembly->array_methods = g_list_prepend (assembly->array_methods, am);
- m->table_idx = am->token & 0xffffff;
- return am->token;
-fail:
- g_free (am);
- g_free (name);
- g_free (sig);
- return 0;
-
-}
-
-/*
- * Insert into the metadata tables all the info about the TypeBuilder tb.
- * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
- */
-static gboolean
-mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- guint *values;
- int i, is_object = 0, is_system = 0;
- char *n;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
- values [MONO_TYPEDEF_FLAGS] = tb->attrs;
- n = mono_string_to_utf8_checked (tb->name, error);
- return_val_if_nok (error, FALSE);
- if (strcmp (n, "Object") == 0)
- is_object++;
- values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
- g_free (n);
- n = mono_string_to_utf8_checked (tb->nspace, error);
- return_val_if_nok (error, FALSE);
- if (strcmp (n, "System") == 0)
- is_system++;
- values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
- g_free (n);
- if (tb->parent && !(is_system && is_object) &&
- !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
- MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
- return_val_if_nok (error, FALSE);
- values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
- } else {
- values [MONO_TYPEDEF_EXTENDS] = 0;
- }
- values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
- values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
-
- /*
- * if we have explicitlayout or sequentiallayouts, output data in the
- * ClassLayout table.
- */
- if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
- ((tb->class_size > 0) || (tb->packing_size > 0))) {
- table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
- values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
- values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
- values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
- }
-
- /* handle interfaces */
- if (tb->interfaces) {
- table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
- i = table->rows;
- table->rows += mono_array_length (tb->interfaces);
- alloc_table (table, table->rows);
- values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
- for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
- MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
- MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
- return_val_if_nok (error, FALSE);
- values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
- values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
- values += MONO_INTERFACEIMPL_SIZE;
- }
- }
-
- /* handle fields */
- if (tb->fields) {
- table = &assembly->tables [MONO_TABLE_FIELD];
- table->rows += tb->num_fields;
- alloc_table (table, table->rows);
- for (i = 0; i < tb->num_fields; ++i) {
- mono_image_get_field_info (
- mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
-
- /* handle constructors */
- if (tb->ctors) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += mono_array_length (tb->ctors);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- if (!mono_image_get_ctor_info (domain,
- mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
- assembly, error))
- return FALSE;
- }
- }
-
- /* handle methods */
- if (tb->methods) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += tb->num_methods;
- alloc_table (table, table->rows);
- for (i = 0; i < tb->num_methods; ++i) {
- if (!mono_image_get_method_info (
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
- return FALSE;
- }
- }
-
- /* Do the same with properties etc.. */
- if (tb->events && mono_array_length (tb->events)) {
- table = &assembly->tables [MONO_TABLE_EVENT];
- table->rows += mono_array_length (tb->events);
- alloc_table (table, table->rows);
- table = &assembly->tables [MONO_TABLE_EVENTMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
- values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
- values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
- for (i = 0; i < mono_array_length (tb->events); ++i) {
- mono_image_get_event_info (
- mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
- if (tb->properties && mono_array_length (tb->properties)) {
- table = &assembly->tables [MONO_TABLE_PROPERTY];
- table->rows += mono_array_length (tb->properties);
- alloc_table (table, table->rows);
- table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
- values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
- values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
- for (i = 0; i < mono_array_length (tb->properties); ++i) {
- mono_image_get_property_info (
- mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
-
- /* handle generic parameters */
- if (tb->generic_params) {
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table->rows += mono_array_length (tb->generic_params);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
- guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
-
- mono_image_get_generic_param_info (
- mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
- }
- }
-
- mono_image_add_decl_security (assembly,
- mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
-
- if (tb->subtypes) {
- MonoDynamicTable *ntable;
-
- ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
- ntable->rows += mono_array_length (tb->subtypes);
- alloc_table (ntable, ntable->rows);
- values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
-
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
-
- values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
- values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
- /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
- mono_string_to_utf8 (subtype->name), subtype->table_idx,
- mono_string_to_utf8 (tb->name), tb->table_idx,
- ntable->next_idx, ntable->rows);*/
- values += MONO_NESTED_CLASS_SIZE;
- ntable->next_idx++;
- }
- }
-
- return TRUE;
-}
-#endif
-
-static void
-collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
-{
- int i;
-
- mono_ptr_array_append (*types, type);
-
- if (!type->subtypes)
- return;
-
- for (i = 0; i < mono_array_length (type->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
- collect_types (types, subtype);
- }
-}
-
-static gint
-compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
-{
- if ((*type1)->table_idx < (*type2)->table_idx)
- return -1;
- else
- if ((*type1)->table_idx > (*type2)->table_idx)
- return 1;
- else
- return 0;
-}
-
-static gboolean
-params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
- int i;
-
- mono_error_init (error);
- if (!pinfo)
- return TRUE;
- for (i = 0; i < mono_array_length (pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
- if (!pb)
- continue;
- if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
- int i;
-
- mono_error_init (error);
-
- if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
- return FALSE;
- if (tb->fields) {
- for (i = 0; i < tb->num_fields; ++i) {
- MonoReflectionFieldBuilder* fb;
- fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
- if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->events) {
- for (i = 0; i < mono_array_length (tb->events); ++i) {
- MonoReflectionEventBuilder* eb;
- eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
- if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->properties) {
- for (i = 0; i < mono_array_length (tb->properties); ++i) {
- MonoReflectionPropertyBuilder* pb;
- pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
- if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->ctors) {
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- MonoReflectionCtorBuilder* cb;
- cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
- if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
- !params_add_cattrs (assembly, cb->pinfo, error))
- return FALSE;
- }
- }
-
- if (tb->methods) {
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder* mb;
- mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
- !params_add_cattrs (assembly, mb->pinfo, error))
- return FALSE;
- }
- }
-
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- int i;
-
- mono_error_init (error);
-
- if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
- return FALSE;
-
- if (moduleb->global_methods) {
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
- !params_add_cattrs (assembly, mb->pinfo, error))
- return FALSE;
- }
- }
-
- if (moduleb->global_fields) {
- for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
- MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
- if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
- return FALSE;
- }
- }
-
- if (moduleb->types) {
- for (i = 0; i < moduleb->num_types; ++i) {
- if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- char blob_size [6];
- guchar hash [20];
- char *b = blob_size;
- char *dir, *path;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_FILE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_FILE_SIZE;
- values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
- values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
- if (image_is_dynamic (module->image)) {
- /* This depends on the fact that the main module is emitted last */
- dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
- return_val_if_nok (error, FALSE);
- path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
- } else {
- dir = NULL;
- path = g_strdup (module->image->name);
- }
- mono_sha1_get_digest_from_file (path, hash);
- g_free (dir);
- g_free (path);
- mono_metadata_encode_value (20, b, &b);
- values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
- table->next_idx ++;
- return TRUE;
-}
-
-static void
-mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- int i;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_MODULE];
- mb->table_idx = table->next_idx ++;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
- return_if_nok (error);
- i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
- i /= 16;
- ++i;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
-}
-
-static guint32
-mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
- guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 visib, res;
-
- visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
- return 0;
-
- table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
-
- values [MONO_EXP_TYPE_FLAGS] = klass->flags;
- values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
- if (klass->nested_in)
- values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
- else
- values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
- values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
-
- res = table->next_idx;
-
- table->next_idx ++;
-
- /* Emit nested types */
- if (klass->ext && klass->ext->nested_classes) {
- GList *tmp;
-
- for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
- mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
- }
-
- return res;
-}
-
-static void
-mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
- guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
- MonoError *error)
-{
- MonoClass *klass;
- guint32 idx, i;
-
- mono_error_init (error);
-
- MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_if_nok (error);
-
- klass = mono_class_from_mono_type (t);
-
- klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
-
- idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
- parent_index, assembly);
-
- /*
- * Emit nested types
- * We need to do this ourselves since klass->nested_classes is not set up.
- */
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
- return_if_nok (error);
- }
- }
-}
-
-static void
-mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
- guint32 module_index, MonoDynamicImage *assembly)
-{
- MonoImage *image = module->image;
- MonoTableInfo *t;
- guint32 i;
-
- t = &image->tables [MONO_TABLE_TYPEDEF];
-
- for (i = 0; i < t->rows; ++i) {
- MonoError error;
- MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
-
- if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
- mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
- }
-}
-
-static void
-add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 scope, scope_idx, impl, current_idx;
- gboolean forwarder = TRUE;
- gpointer iter = NULL;
- MonoClass *nested;
-
- if (klass->nested_in) {
- impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
- forwarder = FALSE;
- } else {
- scope = resolution_scope_from_image (assembly, klass->image);
- g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
- scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
- impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
- }
-
- table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
-
- table->rows++;
- alloc_table (table, table->rows);
- current_idx = table->next_idx;
- values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
-
- values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
- values [MONO_EXP_TYPE_TYPEDEF] = 0;
- values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
- values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
-
- table->next_idx++;
-
- while ((nested = mono_class_get_nested_types (klass, &iter)))
- add_exported_type (assemblyb, assembly, nested, current_idx);
-}
-
-static void
-mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
-{
- MonoError error;
- MonoClass *klass;
- int i;
-
- if (!assemblyb->type_forwarders)
- return;
-
- for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
- MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
- MonoType *type;
- if (!t)
- continue;
-
- type = mono_reflection_type_get_handle (t, &error);
- mono_error_assert_ok (&error);
- g_assert (type);
-
- klass = mono_class_from_mono_type (type);
-
- add_exported_type (assemblyb, assembly, klass, 0);
- }
-}
-
-#define align_pointer(base,p)\
- do {\
- guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
- if (__diff & 3)\
- (p) += 4 - (__diff & 3);\
- } while (0)
-
-static int
-compare_constants (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
- return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
-}
-
-static int
-compare_semantics (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
- int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
- if (assoc)
- return assoc;
- return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
-}
-
-static int
-compare_custom_attrs (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
-}
-
-static int
-compare_field_marshal (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
-}
-
-static int
-compare_nested (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
-}
-
-static int
-compare_genericparam (const void *a, const void *b)
-{
- MonoError error;
- const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
- const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
-
- if ((*b_entry)->owner == (*a_entry)->owner) {
- MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
- mono_error_assert_ok (&error);
- MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
- mono_error_assert_ok (&error);
- return
- mono_type_get_generic_param_num (a_type) -
- mono_type_get_generic_param_num (b_type);
- } else
- return (*a_entry)->owner - (*b_entry)->owner;
-}
-
-static int
-compare_declsecurity_attrs (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
-}
-
-static int
-compare_interface_impl (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
- if (klass)
- return klass;
-
- return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
-}
-
-static void
-pad_heap (MonoDynamicStream *sh)
-{
- if (sh->index & 3) {
- int sz = 4 - (sh->index & 3);
- memset (sh->data + sh->index, 0, sz);
- sh->index += sz;
- }
-}
-
-struct StreamDesc {
- const char *name;
- MonoDynamicStream *stream;
-};
-
-/*
- * build_compressed_metadata() fills in the blob of data that represents the
- * raw metadata as it will be saved in the PE file. The five streams are output
- * and the metadata tables are comnpressed from the guint32 array representation,
- * to the compressed on-disk format.
- */
-static gboolean
-build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- int i;
- guint64 valid_mask = 0;
- guint64 sorted_mask;
- guint32 heapt_size = 0;
- guint32 meta_size = 256; /* allow for header and other stuff */
- guint32 table_offset;
- guint32 ntables = 0;
- guint64 *int64val;
- guint32 *int32val;
- guint16 *int16val;
- MonoImage *meta;
- unsigned char *p;
- struct StreamDesc stream_desc [5];
-
- mono_error_init (error);
-
- qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
- for (i = 0; i < assembly->gen_params->len; i++) {
- GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
- if (!write_generic_param_entry (assembly, entry, error))
- return FALSE;
- }
-
- stream_desc [0].name = "#~";
- stream_desc [0].stream = &assembly->tstream;
- stream_desc [1].name = "#Strings";
- stream_desc [1].stream = &assembly->sheap;
- stream_desc [2].name = "#US";
- stream_desc [2].stream = &assembly->us;
- stream_desc [3].name = "#Blob";
- stream_desc [3].stream = &assembly->blob;
- stream_desc [4].name = "#GUID";
- stream_desc [4].stream = &assembly->guid;
-
- /* tables that are sorted */
- sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
- | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
- | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
- | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
- | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
- | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
- | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
-
- /* Compute table sizes */
- /* the MonoImage has already been created in mono_image_basic_init() */
- meta = &assembly->image;
-
- /* sizes should be multiple of 4 */
- pad_heap (&assembly->blob);
- pad_heap (&assembly->guid);
- pad_heap (&assembly->sheap);
- pad_heap (&assembly->us);
-
- /* Setup the info used by compute_sizes () */
- meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
- meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
- meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
-
- meta_size += assembly->blob.index;
- meta_size += assembly->guid.index;
- meta_size += assembly->sheap.index;
- meta_size += assembly->us.index;
-
- for (i=0; i < MONO_TABLE_NUM; ++i)
- meta->tables [i].rows = assembly->tables [i].rows;
-
- for (i = 0; i < MONO_TABLE_NUM; i++){
- if (meta->tables [i].rows == 0)
- continue;
- valid_mask |= (guint64)1 << i;
- ntables ++;
- meta->tables [i].row_size = mono_metadata_compute_size (
- meta, i, &meta->tables [i].size_bitfield);
- heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
- }
- heapt_size += 24; /* #~ header size */
- heapt_size += ntables * 4;
- /* make multiple of 4 */
- heapt_size += 3;
- heapt_size &= ~3;
- meta_size += heapt_size;
- meta->raw_metadata = (char *)g_malloc0 (meta_size);
- p = (unsigned char*)meta->raw_metadata;
- /* the metadata signature */
- *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
- /* version numbers and 4 bytes reserved */
- int16val = (guint16*)p;
- *int16val++ = GUINT16_TO_LE (meta->md_version_major);
- *int16val = GUINT16_TO_LE (meta->md_version_minor);
- p += 8;
- /* version string */
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
- p += 4;
- memcpy (p, meta->version, strlen (meta->version));
- p += GUINT32_FROM_LE (*int32val);
- align_pointer (meta->raw_metadata, p);
- int16val = (guint16*)p;
- *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
- *int16val = GUINT16_TO_LE (5); /* number of streams */
- p += 4;
-
- /*
- * write the stream info.
- */
- table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
- table_offset += 3; table_offset &= ~3;
-
- assembly->tstream.index = heapt_size;
- for (i = 0; i < 5; ++i) {
- int32val = (guint32*)p;
- stream_desc [i].stream->offset = table_offset;
- *int32val++ = GUINT32_TO_LE (table_offset);
- *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
- table_offset += GUINT32_FROM_LE (*int32val);
- table_offset += 3; table_offset &= ~3;
- p += 8;
- strcpy ((char*)p, stream_desc [i].name);
- p += strlen (stream_desc [i].name) + 1;
- align_pointer (meta->raw_metadata, p);
- }
- /*
- * now copy the data, the table stream header and contents goes first.
- */
- g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
- p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE (0); /* reserved */
- p += 4;
-
- *p++ = 2; /* version */
- *p++ = 0;
-
- if (meta->idx_string_wide)
- *p |= 0x01;
- if (meta->idx_guid_wide)
- *p |= 0x02;
- if (meta->idx_blob_wide)
- *p |= 0x04;
- ++p;
- *p++ = 1; /* reserved */
- int64val = (guint64*)p;
- *int64val++ = GUINT64_TO_LE (valid_mask);
- *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
- p += 16;
- int32val = (guint32*)p;
- for (i = 0; i < MONO_TABLE_NUM; i++){
- if (meta->tables [i].rows == 0)
- continue;
- *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
- }
- p = (unsigned char*)int32val;
-
- /* sort the tables that still need sorting */
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- if (table->rows)
- qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- if (table->rows)
- qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- if (table->rows)
- qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
- table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- if (table->rows)
- qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
- table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
- if (table->rows)
- qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
- /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
- table = &assembly->tables [MONO_TABLE_DECLSECURITY];
- if (table->rows)
- qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
- table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
- if (table->rows)
- qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
-
- /* compress the tables */
- for (i = 0; i < MONO_TABLE_NUM; i++){
- int row, col;
- guint32 *values;
- guint32 bitfield = meta->tables [i].size_bitfield;
- if (!meta->tables [i].rows)
- continue;
- if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
- g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
- meta->tables [i].base = (char*)p;
- for (row = 1; row <= meta->tables [i].rows; ++row) {
- values = assembly->tables [i].values + row * assembly->tables [i].columns;
- for (col = 0; col < assembly->tables [i].columns; ++col) {
- switch (mono_metadata_table_size (bitfield, col)) {
- case 1:
- *p++ = values [col];
- break;
- case 2:
- *p++ = values [col] & 0xff;
- *p++ = (values [col] >> 8) & 0xff;
- break;
- case 4:
- *p++ = values [col] & 0xff;
- *p++ = (values [col] >> 8) & 0xff;
- *p++ = (values [col] >> 16) & 0xff;
- *p++ = (values [col] >> 24) & 0xff;
- break;
- default:
- g_assert_not_reached ();
- }
- }
- }
- g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
- }
-
- g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
- memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
- memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
- memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
- memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
-
- assembly->meta_size = assembly->guid.offset + assembly->guid.index;
-
- return TRUE;
-}
-
-/*
- * Some tables in metadata need to be sorted according to some criteria, but
- * when methods and fields are first created with reflection, they may be assigned a token
- * that doesn't correspond to the final token they will get assigned after the sorting.
- * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
- * with the reflection objects that represent them. Once all the tables are set up, the
- * reflection objects will contains the correct table index. fixup_method() will fixup the
- * tokens for the method with ILGenerator @ilgen.
- */
-static void
-fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
-{
- guint32 code_idx = GPOINTER_TO_UINT (value);
- MonoReflectionILTokenInfo *iltoken;
- MonoReflectionFieldBuilder *field;
- MonoReflectionCtorBuilder *ctor;
- MonoReflectionMethodBuilder *method;
- MonoReflectionTypeBuilder *tb;
- MonoReflectionArrayMethod *am;
- guint32 i, idx = 0;
- unsigned char *target;
-
- for (i = 0; i < ilgen->num_token_fixups; ++i) {
- iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
- target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
- switch (target [3]) {
- case MONO_TABLE_FIELD:
- if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
- field = (MonoReflectionFieldBuilder *)iltoken->member;
- idx = field->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
- MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_METHOD:
- if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
- method = (MonoReflectionMethodBuilder *)iltoken->member;
- idx = method->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
- ctor = (MonoReflectionCtorBuilder *)iltoken->member;
- idx = ctor->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_TYPEDEF:
- if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
- g_assert_not_reached ();
- tb = (MonoReflectionTypeBuilder *)iltoken->member;
- idx = tb->table_idx;
- break;
- case MONO_TABLE_MEMBERREF:
- if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
- am = (MonoReflectionArrayMethod*)iltoken->member;
- idx = am->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (m->klass->generic_class || m->klass->generic_container);
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
- MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
- g_assert (is_field_on_inst (f));
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
- !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
- continue;
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_METHODSPEC:
- if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (mono_method_signature (m)->generic_param_count);
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
- continue;
- } else {
- g_assert_not_reached ();
- }
- break;
- default:
- g_error ("got unexpected table 0x%02x in fixup", target [3]);
- }
- target [0] = idx & 0xff;
- target [1] = (idx >> 8) & 0xff;
- target [2] = (idx >> 16) & 0xff;
- }
-}
-
-/*
- * fixup_cattrs:
- *
- * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
- * value is not known when the table is emitted.
- */
-static void
-fixup_cattrs (MonoDynamicImage *assembly)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 type, i, idx, token;
- MonoObject *ctor;
-
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-
- for (i = 0; i < table->rows; ++i) {
- values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
-
- type = values [MONO_CUSTOM_ATTR_TYPE];
- if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
- idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
- token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
- ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
- g_assert (ctor);
-
- if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
- MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- }
- }
- }
-}
-
-static gboolean
-assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
- values [MONO_MANIFEST_OFFSET] = rsrc->offset;
- values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
- values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
- return_val_if_nok (error, FALSE);
- values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
- table->next_idx++;
- return TRUE;
-}
-
-static gboolean
-assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- char blob_size [6];
- guchar hash [20];
- char *b = blob_size;
- char *name, *sname;
- guint32 idx, offset;
-
- mono_error_init (error);
-
- if (rsrc->filename) {
- name = mono_string_to_utf8_checked (rsrc->filename, error);
- return_val_if_nok (error, FALSE);
- sname = g_path_get_basename (name);
-
- table = &assembly->tables [MONO_TABLE_FILE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_FILE_SIZE;
- values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
- values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
- g_free (sname);
-
- mono_sha1_get_digest_from_file (name, hash);
- mono_metadata_encode_value (20, b, &b);
- values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
- g_free (name);
- idx = table->next_idx++;
- rsrc->offset = 0;
- idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
- } else {
- char sizebuf [4];
- char *data;
- guint len;
- if (rsrc->data) {
- data = mono_array_addr (rsrc->data, char, 0);
- len = mono_array_length (rsrc->data);
- } else {
- data = NULL;
- len = 0;
- }
- offset = len;
- sizebuf [0] = offset; sizebuf [1] = offset >> 8;
- sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
- rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
- mono_image_add_stream_data (&assembly->resources, data, len);
-
- if (!mb->is_main)
- /*
- * The entry should be emitted into the MANIFESTRESOURCE table of
- * the main module, but that needs to reference the FILE table
- * which isn't emitted yet.
- */
- return TRUE;
- else
- idx = 0;
- }
-
- return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
-}
-
-static gboolean
-set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
-{
- gchar *ver, *p, *str;
- guint32 i;
-
- mono_error_init (error);
-
- values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
- values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
- values [MONO_ASSEMBLY_REV_NUMBER] = 0;
- values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
- if (!version)
- return TRUE;
- ver = str = mono_string_to_utf8_checked (version, error);
- return_val_if_nok (error, FALSE);
- for (i = 0; i < 4; ++i) {
- values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
- switch (*p) {
- case '.':
- p++;
- break;
- case '*':
- /* handle Revision and Build */
- p++;
- break;
- }
- ver = p;
- }
- g_free (str);
- return TRUE;
-}
-
-static guint32
-load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
- gsize len;
- guint32 token = 0;
- char blob_size [6];
- char *b = blob_size;
-
- if (!pkey)
- return token;
-
- len = mono_array_length (pkey);
- mono_metadata_encode_value (len, b, &b);
- token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
- mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
-
- assembly->public_key = (guint8 *)g_malloc (len);
- memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
- assembly->public_key_len = len;
-
- /* Special case: check for ECMA key (16 bytes) */
- if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
- /* In this case we must reserve 128 bytes (1024 bits) for the signature */
- assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
- } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
- /* minimum key size (in 2.0) is 384 bits */
- assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
- } else {
- /* FIXME - verifier */
- g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
- assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
- }
- assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
-
- return token;
-}
-
-static gboolean
-mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDomain *domain;
- guint32 *values;
- int i;
- guint32 module_index;
-
- mono_error_init (error);
-
- assemblyb = moduleb->assemblyb;
- assembly = moduleb->dynamic_image;
- domain = mono_object_domain (assemblyb);
-
- /* Emit ASSEMBLY table */
- table = &assembly->tables [MONO_TABLE_ASSEMBLY];
- alloc_table (table, 1);
- values = table->values + MONO_ASSEMBLY_SIZE;
- values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
- values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
- return_val_if_nok (error, FALSE);
- if (assemblyb->culture) {
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
- return_val_if_nok (error, FALSE);
- } else {
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
- }
- values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
- values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
- if (!set_version_from_string (assemblyb->version, values, error))
- return FALSE;
-
- /* Emit FILE + EXPORTED_TYPE table */
- module_index = 0;
- for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
- int j;
- MonoReflectionModuleBuilder *file_module =
- mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
- if (file_module != moduleb) {
- if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
- return FALSE;
- module_index ++;
- if (file_module->types) {
- for (j = 0; j < file_module->num_types; ++j) {
- MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
- mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
- }
- }
- if (assemblyb->loaded_modules) {
- for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
- MonoReflectionModule *file_module =
- mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
- if (!mono_image_fill_file_table (domain, file_module, assembly, error))
- return FALSE;
- module_index ++;
- mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
- }
- }
- if (assemblyb->type_forwarders)
- mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
-
- /* Emit MANIFESTRESOURCE table */
- module_index = 0;
- for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
- int j;
- MonoReflectionModuleBuilder *file_module =
- mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
- /* The table for the main module is emitted later */
- if (file_module != moduleb) {
- module_index ++;
- if (file_module->resources) {
- int len = mono_array_length (file_module->resources);
- for (j = 0; j < len; ++j) {
- MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
- if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
- return FALSE;
- }
- }
- }
- }
- return TRUE;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT_SAVE
-
-/*
- * mono_image_build_metadata() will fill the info in all the needed metadata tables
- * for the modulebuilder @moduleb.
- * At the end of the process, method and field tokens are fixed up and the
- * on-disk compressed metadata representation is created.
- * Return TRUE on success, or FALSE on failure and sets @error
- */
-gboolean
-mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDomain *domain;
- MonoPtrArray types;
- guint32 *values;
- int i, j;
-
- mono_error_init (error);
-
- assemblyb = moduleb->assemblyb;
- assembly = moduleb->dynamic_image;
- domain = mono_object_domain (assemblyb);
-
- if (assembly->text_rva)
- return TRUE;
-
- assembly->text_rva = START_TEXT_RVA;
-
- if (moduleb->is_main) {
- mono_image_emit_manifest (moduleb, error);
- return_val_if_nok (error, FALSE);
- }
-
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows = 1; /* .<Module> */
- table->next_idx++;
- alloc_table (table, table->rows);
- /*
- * Set the first entry.
- */
- values = table->values + table->columns;
- values [MONO_TYPEDEF_FLAGS] = 0;
- values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
- values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
- values [MONO_TYPEDEF_EXTENDS] = 0;
- values [MONO_TYPEDEF_FIELD_LIST] = 1;
- values [MONO_TYPEDEF_METHOD_LIST] = 1;
-
- /*
- * handle global methods
- * FIXME: test what to do when global methods are defined in multiple modules.
- */
- if (moduleb->global_methods) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += mono_array_length (moduleb->global_methods);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- if (!mono_image_get_method_info (
- mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
- goto leave;
- }
- }
- if (moduleb->global_fields) {
- table = &assembly->tables [MONO_TABLE_FIELD];
- table->rows += mono_array_length (moduleb->global_fields);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
- mono_image_get_field_info (
- mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
- error);
- if (!is_ok (error))
- goto leave;
- }
- }
-
- table = &assembly->tables [MONO_TABLE_MODULE];
- alloc_table (table, 1);
- mono_image_fill_module_table (domain, moduleb, assembly, error);
- if (!is_ok (error))
- goto leave;
-
- /* Collect all types into a list sorted by their table_idx */
- mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
-
- if (moduleb->types)
- for (i = 0; i < moduleb->num_types; ++i) {
- MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
- collect_types (&types, type);
- }
-
- mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_ptr_array_size (types);
- alloc_table (table, table->rows);
-
- /*
- * Emit type names + namespaces at one place inside the string heap,
- * so load_class_names () needs to touch fewer pages.
- */
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
- if (!is_ok (error))
- goto leave_types;
- }
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- string_heap_insert_mstring (&assembly->sheap, tb->name, error);
- if (!is_ok (error))
- goto leave_types;
- }
-
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- if (!mono_image_get_type_info (domain, type, assembly, error))
- goto leave_types;
- }
-
- /*
- * table->rows is already set above and in mono_image_fill_module_table.
- */
- /* add all the custom attributes at the end, once all the indexes are stable */
- if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
- goto leave_types;
-
- /* CAS assembly permissions */
- if (assemblyb->permissions_minimum)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
- if (assemblyb->permissions_optional)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
- if (assemblyb->permissions_refused)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
-
- if (!module_add_cattrs (assembly, moduleb, error))
- goto leave_types;
-
- /* fixup tokens */
- mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-
- /* Create the MethodImpl table. We do this after emitting all methods so we already know
- * the final tokens and don't need another fixup pass. */
-
- if (moduleb->global_methods) {
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- MonoReflectionMethodBuilder *mb = mono_array_get (
- moduleb->global_methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_methodimpl (assembly, mb, error))
- goto leave_types;
- }
- }
-
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- if (type->methods) {
- for (j = 0; j < type->num_methods; ++j) {
- MonoReflectionMethodBuilder *mb = mono_array_get (
- type->methods, MonoReflectionMethodBuilder*, j);
-
- if (!mono_image_add_methodimpl (assembly, mb, error))
- goto leave_types;
- }
- }
- }
-
- fixup_cattrs (assembly);
-
-leave_types:
- mono_ptr_array_destroy (types);
-leave:
-
- return mono_error_ok (error);
-}
-
-#else /* DISABLE_REFLECTION_EMIT_SAVE */
-
-gboolean
-mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
-}
-
-#endif /* DISABLE_REFLECTION_EMIT_SAVE */
-
-
-typedef struct {
- guint32 import_lookup_table;
- guint32 timestamp;
- guint32 forwarder;
- guint32 name_rva;
- guint32 import_address_table_rva;
-} MonoIDT;
-
-typedef struct {
- guint32 name_rva;
- guint32 flags;
-} MonoILT;
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-/*
- * mono_image_insert_string:
- * @module: module builder object
- * @str: a string
- *
- * Insert @str into the user string stream of @module.
- */
-guint32
-mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
-{
- MonoDynamicImage *assembly;
- guint32 idx;
- char buf [16];
- char *b = buf;
-
- if (!module->dynamic_image)
- mono_image_module_basic_init (module);
-
- assembly = module->dynamic_image;
-
- if (assembly->save) {
- mono_metadata_encode_value (1 | (str->length * 2), b, &b);
- idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
-
- swap_with_size (swapped, p, 2, mono_string_length (str));
- mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
- g_free (swapped);
- }
-#else
- mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
-#endif
- mono_image_add_stream_data (&assembly->us, "", 1);
- } else {
- idx = assembly->us.index ++;
- }
-
- register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
-
- return MONO_TOKEN_STRING | idx;
-}
-
-guint32
-mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
- if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
- MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
- MonoMethodSignature *old;
- guint32 sig_token, parent;
- int nargs, i;
-
- g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
-
- nargs = mono_array_length (opt_param_types);
- old = mono_method_signature (method);
- sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
-
- sig->hasthis = old->hasthis;
- sig->explicit_this = old->explicit_this;
- sig->call_convention = old->call_convention;
- sig->generic_param_count = old->generic_param_count;
- sig->param_count = old->param_count + nargs;
- sig->sentinelpos = old->param_count;
- sig->ret = old->ret;
-
- for (i = 0; i < old->param_count; i++)
- sig->params [i] = old->params [i];
-
- for (i = 0; i < nargs; i++) {
- MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
- sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
- g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- parent <<= MONO_MEMBERREF_PARENT_BITS;
- parent |= MONO_MEMBERREF_PARENT_TYPEREF;
-
- sig_token = method_encode_signature (assembly, sig);
- token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
- } else if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- ReflectionMethodBuilder rmb;
- guint32 parent, sig_token;
- int nopt_args, nparams, ngparams, i;
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- goto fail;
-
- rmb.opt_types = opt_param_types;
- nopt_args = mono_array_length (opt_param_types);
-
- nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
- ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
- sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
-
- sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
- sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
- sig->call_convention = rmb.call_conv;
- sig->generic_param_count = ngparams;
- sig->param_count = nparams + nopt_args;
- sig->sentinelpos = nparams;
- sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
- if (!is_ok (error)) goto fail;
-
- for (i = 0; i < nparams; i++) {
- MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
- sig->params [i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- for (i = 0; i < nopt_args; i++) {
- MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
- sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- sig_token = method_builder_encode_signature (assembly, &rmb, error);
- if (!is_ok (error))
- goto fail;
-
- parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
- if (!mono_error_ok (error))
- goto fail;
- g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
-
- parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
- parent |= MONO_MEMBERREF_PARENT_METHODDEF;
-
- char *name = mono_string_to_utf8_checked (rmb.name, error);
- if (!is_ok (error)) goto fail;
- token = mono_image_get_varargs_method_token (
- assembly, parent, name, sig_token);
- g_free (name);
- } else {
- g_error ("requested method token for %s\n", klass->name);
- }
-
- g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
- register_dyn_token (assembly, token, obj);
- return token;
-fail:
- g_assert (!mono_error_ok (error));
- return 0;
-}
-
-/*
- * mono_image_create_token:
- * @assembly: a dynamic assembly
- * @obj:
- * @register_token: Whenever to register the token in the assembly->tokens hash.
- *
- * Get a token to insert in the IL code stream for the given MemberInfo.
- * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
- * the table_idx-es were recomputed, so registering the token would overwrite an existing
- * entry.
- */
-guint32
-mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
- gboolean create_open_instance, gboolean register_token,
- MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
-
- /* Check for user defined reflection objects */
- /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
- if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
- mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
- return 0;
- }
-
- if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- else {
- token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- }
- /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- if (tb->module->dynamic_image == assembly && !tb->generic_params)
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- else {
- token = mono_image_get_ctorbuilder_token (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
- }
- /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- } else if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
- if (tb->generic_params) {
- token = mono_image_get_generic_field_token (assembly, fb, error);
- return_val_if_nok (error, 0);
- } else {
- if (tb->module->dynamic_image == assembly) {
- token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
- } else {
- token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
- }
- }
- } else if (strcmp (klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- if (create_open_instance && tb->generic_params) {
- MonoType *type;
- init_type_builder_generics (obj, error);
- return_val_if_nok (error, 0);
- type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
- token = mono_metadata_token_from_dor (token);
- } else if (tb->module->dynamic_image == assembly) {
- token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
- } else {
- MonoType *type;
- type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
- }
- } else if (strcmp (klass->name, "RuntimeType") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- MonoClass *mc = mono_class_from_mono_type (type);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
- } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
- strcmp (klass->name, "MonoMethod") == 0 ||
- strcmp (klass->name, "MonoGenericMethod") == 0 ||
- strcmp (klass->name, "MonoGenericCMethod") == 0) {
- MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
- if (m->method->is_inflated) {
- if (create_open_instance)
- token = mono_image_get_methodspec_token (assembly, m->method);
- else
- token = mono_image_get_inflated_method_token (assembly, m->method);
- } else if ((m->method->klass->image == &assembly->image) &&
- !m->method->klass->generic_class) {
- static guint32 method_table_idx = 0xffffff;
- if (m->method->klass->wastypebuilder) {
- /* we use the same token as the one that was assigned
- * to the Methodbuilder.
- * FIXME: do the equivalent for Fields.
- */
- token = m->method->token;
- } else {
- /*
- * Each token should have a unique index, but the indexes are
- * assigned by managed code, so we don't know about them. An
- * easy solution is to count backwards...
- */
- method_table_idx --;
- token = MONO_TOKEN_METHOD_DEF | method_table_idx;
- }
- } else {
- token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
- }
- /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
- } else if (strcmp (klass->name, "MonoField") == 0) {
- MonoReflectionField *f = (MonoReflectionField *)obj;
- if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
- static guint32 field_table_idx = 0xffffff;
- field_table_idx --;
- token = MONO_TOKEN_FIELD_DEF | field_table_idx;
- } else {
- token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
- }
- /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
- } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
- MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
- token = mono_image_get_array_token (assembly, m, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "SignatureHelper") == 0) {
- MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
- token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "EnumBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
- MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
- token = mono_image_get_field_on_inst_token (assembly, f, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
- token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
- token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else {
- g_error ("requested token for %s\n", klass->name);
- }
-
- if (register_token)
- mono_image_register_token (assembly, token, obj);
-
- return token;
-}
-
-/*
- * mono_image_register_token:
- *
- * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
- * the Module.ResolveXXXToken () methods to work.
- */
-void
-mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
-{
- MonoObject *prev;
-
- dynamic_image_lock (assembly);
- prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
- if (prev) {
- /* There could be multiple MethodInfo objects with the same token */
- //g_assert (prev == obj);
- } else {
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
- }
- dynamic_image_unlock (assembly);
-}
-
-static MonoDynamicImage*
-create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
-{
- static const guchar entrycode [16] = {0xff, 0x25, 0};
- MonoDynamicImage *image;
- int i;
-
- const char *version;
-
- if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
- version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
- else
- version = mono_get_runtime_info ()->runtime_version;
-
-#if HAVE_BOEHM_GC
- /* The MonoGHashTable's need GC tracking */
- image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
-#else
- image = g_new0 (MonoDynamicImage, 1);
-#endif
-
- mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
-
- /*g_print ("created image %p\n", image);*/
- /* keep in sync with image.c */
- image->image.name = assembly_name;
- image->image.assembly_name = image->image.name; /* they may be different */
- image->image.module_name = module_name;
- image->image.version = g_strdup (version);
- image->image.md_version_major = 1;
- image->image.md_version_minor = 1;
- image->image.dynamic = TRUE;
-
- image->image.references = g_new0 (MonoAssembly*, 1);
- image->image.references [0] = NULL;
-
- mono_image_init (&image->image);
-
- image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
- image->method_to_table_idx = g_hash_table_new (NULL, NULL);
- image->field_to_table_idx = g_hash_table_new (NULL, NULL);
- image->method_aux_hash = g_hash_table_new (NULL, NULL);
- image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
- image->handleref = g_hash_table_new (NULL, NULL);
- image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
- image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
- image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
- image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
- image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
- image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
- image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
- image->gen_params = g_ptr_array_new ();
- image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
-
- /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
- string_heap_init (&image->sheap);
- mono_image_add_stream_data (&image->us, "", 1);
- add_to_blob_cached (image, (char*) "", 1, NULL, 0);
- /* import tables... */
- mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
- image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
- image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
- image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
- mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
- mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
- image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
- stream_data_align (&image->code);
-
- image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
-
- for (i=0; i < MONO_TABLE_NUM; ++i) {
- image->tables [i].next_idx = 1;
- image->tables [i].columns = table_sizes [i];
- }
-
- image->image.assembly = (MonoAssembly*)assembly;
- image->run = assembly->run;
- image->save = assembly->save;
- image->pe_kind = 0x1; /* ILOnly */
- image->machine = 0x14c; /* I386 */
-
- mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
-
- dynamic_images_lock ();
-
- if (!dynamic_images)
- dynamic_images = g_ptr_array_new ();
-
- g_ptr_array_add (dynamic_images, image);
-
- dynamic_images_unlock ();
-
- return image;
-}
-#endif
-
-static void
-free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
-{
- g_free (key);
-}
-
-static void
-release_hashtable (MonoGHashTable **hash)
-{
- if (*hash) {
- mono_g_hash_table_destroy (*hash);
- *hash = NULL;
- }
-}
-
-void
-mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
-{
- release_hashtable (&image->token_fixups);
- release_hashtable (&image->handleref_managed);
- release_hashtable (&image->tokens);
- release_hashtable (&image->remapped_tokens);
- release_hashtable (&image->generic_def_objects);
- release_hashtable (&image->methodspec);
-}
-
-// Free dynamic image pass one: Free resources but not image itself
-void
-mono_dynamic_image_free (MonoDynamicImage *image)
-{
- MonoDynamicImage *di = image;
- GList *list;
- int i;
-
- if (di->methodspec)
- mono_g_hash_table_destroy (di->methodspec);
- if (di->typespec)
- g_hash_table_destroy (di->typespec);
- if (di->typeref)
- g_hash_table_destroy (di->typeref);
- if (di->handleref)
- g_hash_table_destroy (di->handleref);
- if (di->handleref_managed)
- mono_g_hash_table_destroy (di->handleref_managed);
- if (di->tokens)
- mono_g_hash_table_destroy (di->tokens);
- if (di->remapped_tokens)
- mono_g_hash_table_destroy (di->remapped_tokens);
- if (di->generic_def_objects)
- mono_g_hash_table_destroy (di->generic_def_objects);
- if (di->blob_cache) {
- g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
- g_hash_table_destroy (di->blob_cache);
- }
- if (di->standalonesig_cache)
- g_hash_table_destroy (di->standalonesig_cache);
- for (list = di->array_methods; list; list = list->next) {
- ArrayMethod *am = (ArrayMethod *)list->data;
- g_free (am->sig);
- g_free (am->name);
- g_free (am);
- }
- g_list_free (di->array_methods);
- if (di->gen_params) {
- for (i = 0; i < di->gen_params->len; i++) {
- GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
- mono_gc_deregister_root ((char*) &entry->gparam);
- g_free (entry);
- }
- g_ptr_array_free (di->gen_params, TRUE);
- }
- if (di->token_fixups)
- mono_g_hash_table_destroy (di->token_fixups);
- if (di->method_to_table_idx)
- g_hash_table_destroy (di->method_to_table_idx);
- if (di->field_to_table_idx)
- g_hash_table_destroy (di->field_to_table_idx);
- if (di->method_aux_hash)
- g_hash_table_destroy (di->method_aux_hash);
- if (di->vararg_aux_hash)
- g_hash_table_destroy (di->vararg_aux_hash);
- g_free (di->strong_name);
- g_free (di->win32_res);
- if (di->public_key)
- g_free (di->public_key);
-
- /*g_print ("string heap destroy for image %p\n", di);*/
- mono_dynamic_stream_reset (&di->sheap);
- mono_dynamic_stream_reset (&di->code);
- mono_dynamic_stream_reset (&di->resources);
- mono_dynamic_stream_reset (&di->us);
- mono_dynamic_stream_reset (&di->blob);
- mono_dynamic_stream_reset (&di->tstream);
- mono_dynamic_stream_reset (&di->guid);
- for (i = 0; i < MONO_TABLE_NUM; ++i) {
- g_free (di->tables [i].values);
- }
-
- dynamic_images_lock ();
-
- if (dynamic_images)
- g_ptr_array_remove (dynamic_images, di);
-
- dynamic_images_unlock ();
-}
-
-// Free dynamic image pass two: Free image itself (might never get called in some debug modes)
-void
-mono_dynamic_image_free_image (MonoDynamicImage *image)
-{
- /* See create_dynamic_mono_image () */
-#if HAVE_BOEHM_GC
- /* Allocated using GC_MALLOC */
-#else
- g_free (image);
-#endif
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-/*
- * mono_image_basic_init:
- * @assembly: an assembly builder object
- *
- * Create the MonoImage that represents the assembly builder and setup some
- * of the helper hash table and the basic metadata streams.
- */
-static void
-mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
-{
- MonoError error;
- MonoDynamicAssembly *assembly;
- MonoDynamicImage *image;
- MonoDomain *domain = mono_object_domain (assemblyb);
-
- if (assemblyb->dynamic_assembly)
- return;
-
-#if HAVE_BOEHM_GC
- /* assembly->assembly.image might be GC allocated */
- assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
-#else
- assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
-#endif
-
- mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
-
- assembly->assembly.ref_count = 1;
- assembly->assembly.dynamic = TRUE;
- assembly->assembly.corlib_internal = assemblyb->corlib_internal;
- assemblyb->assembly.assembly = (MonoAssembly*)assembly;
- assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- if (assemblyb->culture) {
- assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- } else
- assembly->assembly.aname.culture = g_strdup ("");
-
- if (assemblyb->version) {
- char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- char **version = g_strsplit (vstr, ".", 4);
- char **parts = version;
- assembly->assembly.aname.major = atoi (*parts++);
- assembly->assembly.aname.minor = atoi (*parts++);
- assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
- assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
-
- g_strfreev (version);
- g_free (vstr);
- } else {
- assembly->assembly.aname.major = 0;
- assembly->assembly.aname.minor = 0;
- assembly->assembly.aname.build = 0;
- assembly->assembly.aname.revision = 0;
- }
-
- assembly->run = assemblyb->access != 2;
- assembly->save = assemblyb->access != 1;
- assembly->domain = domain;
-
- char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
- image->initial_image = TRUE;
- assembly->assembly.aname.name = image->image.name;
- assembly->assembly.image = &image->image;
- if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
- /* -1 to correct for the trailing NULL byte */
- if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
- g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
- }
- memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
- }
-
- mono_domain_assemblies_lock (domain);
- domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
- mono_domain_assemblies_unlock (domain);
-
- register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
-
- mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
-
- mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
-}
-
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-#ifndef DISABLE_REFLECTION_EMIT_SAVE
-
-static int
-calc_section_size (MonoDynamicImage *assembly)
-{
- int nsections = 0;
-
- /* alignment constraints */
- mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
- g_assert ((assembly->code.index % 4) == 0);
- assembly->meta_size += 3;
- assembly->meta_size &= ~3;
- mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
- g_assert ((assembly->resources.index % 4) == 0);
-
- assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
- assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
- nsections++;
-
- if (assembly->win32_res) {
- guint32 res_size = (assembly->win32_res_size + 3) & ~3;
-
- assembly->sections [MONO_SECTION_RSRC].size = res_size;
- assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
- nsections++;
- }
-
- assembly->sections [MONO_SECTION_RELOC].size = 12;
- assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
- nsections++;
-
- return nsections;
-}
-
-typedef struct {
- guint32 id;
- guint32 offset;
- GSList *children;
- MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
-} ResTreeNode;
-
-static int
-resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
-{
- ResTreeNode *t1 = (ResTreeNode*)a;
- ResTreeNode *t2 = (ResTreeNode*)b;
-
- return t1->id - t2->id;
-}
-
-/*
- * resource_tree_create:
- *
- * Organize the resources into a resource tree.
- */
-static ResTreeNode *
-resource_tree_create (MonoArray *win32_resources)
-{
- ResTreeNode *tree, *res_node, *type_node, *lang_node;
- GSList *l;
- int i;
-
- tree = g_new0 (ResTreeNode, 1);
-
- for (i = 0; i < mono_array_length (win32_resources); ++i) {
- MonoReflectionWin32Resource *win32_res =
- (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
-
- /* Create node */
-
- /* FIXME: BUG: this stores managed references in unmanaged memory */
- lang_node = g_new0 (ResTreeNode, 1);
- lang_node->id = win32_res->lang_id;
- lang_node->win32_res = win32_res;
-
- /* Create type node if neccesary */
- type_node = NULL;
- for (l = tree->children; l; l = l->next)
- if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
- type_node = (ResTreeNode*)l->data;
- break;
- }
-
- if (!type_node) {
- type_node = g_new0 (ResTreeNode, 1);
- type_node->id = win32_res->res_type;
-
- /*
- * The resource types have to be sorted otherwise
- * Windows Explorer can't display the version information.
- */
- tree->children = g_slist_insert_sorted (tree->children,
- type_node, resource_tree_compare_by_id);
- }
-
- /* Create res node if neccesary */
- res_node = NULL;
- for (l = type_node->children; l; l = l->next)
- if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
- res_node = (ResTreeNode*)l->data;
- break;
- }
-
- if (!res_node) {
- res_node = g_new0 (ResTreeNode, 1);
- res_node->id = win32_res->res_id;
- type_node->children = g_slist_append (type_node->children, res_node);
- }
-
- res_node->children = g_slist_append (res_node->children, lang_node);
- }
-
- return tree;
-}
-
-/*
- * resource_tree_encode:
- *
- * Encode the resource tree into the format used in the PE file.
- */
-static void
-resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
-{
- char *entries;
- MonoPEResourceDir dir;
- MonoPEResourceDirEntry dir_entry;
- MonoPEResourceDataEntry data_entry;
- GSList *l;
- guint32 res_id_entries;
-
- /*
- * For the format of the resource directory, see the article
- * "An In-Depth Look into the Win32 Portable Executable File Format" by
- * Matt Pietrek
- */
-
- memset (&dir, 0, sizeof (dir));
- memset (&dir_entry, 0, sizeof (dir_entry));
- memset (&data_entry, 0, sizeof (data_entry));
-
- g_assert (sizeof (dir) == 16);
- g_assert (sizeof (dir_entry) == 8);
- g_assert (sizeof (data_entry) == 16);
-
- node->offset = p - begin;
-
- /* IMAGE_RESOURCE_DIRECTORY */
- res_id_entries = g_slist_length (node->children);
- dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
-
- memcpy (p, &dir, sizeof (dir));
- p += sizeof (dir);
-
- /* Reserve space for entries */
- entries = p;
- p += sizeof (dir_entry) * res_id_entries;
-
- /* Write children */
- for (l = node->children; l; l = l->next) {
- ResTreeNode *child = (ResTreeNode*)l->data;
-
- if (child->win32_res) {
- guint32 size;
-
- child->offset = p - begin;
-
- /* IMAGE_RESOURCE_DATA_ENTRY */
- data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
- size = mono_array_length (child->win32_res->res_data);
- data_entry.rde_size = GUINT32_TO_LE (size);
-
- memcpy (p, &data_entry, sizeof (data_entry));
- p += sizeof (data_entry);
-
- memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
- p += size;
- } else {
- resource_tree_encode (child, begin, p, &p);
- }
- }
-
- /* IMAGE_RESOURCE_ENTRY */
- for (l = node->children; l; l = l->next) {
- ResTreeNode *child = (ResTreeNode*)l->data;
-
- MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
- MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
-
- memcpy (entries, &dir_entry, sizeof (dir_entry));
- entries += sizeof (dir_entry);
- }
-
- *endbuf = p;
-}
-
-static void
-resource_tree_free (ResTreeNode * node)
-{
- GSList * list;
- for (list = node->children; list; list = list->next)
- resource_tree_free ((ResTreeNode*)list->data);
- g_slist_free(node->children);
- g_free (node);
-}
-
-static void
-assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
-{
- char *buf;
- char *p;
- guint32 size, i;
- MonoReflectionWin32Resource *win32_res;
- ResTreeNode *tree;
-
- if (!assemblyb->win32_resources)
- return;
-
- /*
- * Resources are stored in a three level tree inside the PE file.
- * - level one contains a node for each type of resource
- * - level two contains a node for each resource
- * - level three contains a node for each instance of a resource for a
- * specific language.
- */
-
- tree = resource_tree_create (assemblyb->win32_resources);
-
- /* Estimate the size of the encoded tree */
- size = 0;
- for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
- win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
- size += mono_array_length (win32_res->res_data);
- }
- /* Directory structure */
- size += mono_array_length (assemblyb->win32_resources) * 256;
- p = buf = (char *)g_malloc (size);
-
- resource_tree_encode (tree, p, p, &p);
-
- g_assert (p - buf <= size);
-
- assembly->win32_res = (char *)g_malloc (p - buf);
- assembly->win32_res_size = p - buf;
- memcpy (assembly->win32_res, buf, p - buf);
-
- g_free (buf);
- resource_tree_free (tree);
-}
-
-static void
-fixup_resource_directory (char *res_section, char *p, guint32 rva)
-{
- MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
- int i;
-
- p += sizeof (MonoPEResourceDir);
- for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
- MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
- char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
- if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
- fixup_resource_directory (res_section, child, rva);
- } else {
- MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
- data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
- }
-
- p += sizeof (MonoPEResourceDirEntry);
- }
-}
-
-static void
-checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
-{
- guint32 dummy;
- if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
- g_error ("WriteFile returned %d\n", GetLastError ());
-}
-
-/*
- * mono_image_create_pefile:
- * @mb: a module builder object
- *
- * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
- * assembly->pefile where it can be easily retrieved later in chunks.
- */
-gboolean
-mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
-{
- MonoMSDOSHeader *msdos;
- MonoDotNetHeader *header;
- MonoSectionTable *section;
- MonoCLIHeader *cli_header;
- guint32 size, image_size, virtual_base, text_offset;
- guint32 header_start, section_start, file_offset, virtual_offset;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDynamicStream pefile_stream = {0};
- MonoDynamicStream *pefile = &pefile_stream;
- int i, nsections;
- guint32 *rva, value;
- guchar *p;
- static const unsigned char msheader[] = {
- 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
- 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
- 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
- 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- mono_error_init (error);
-
- assemblyb = mb->assemblyb;
-
- mono_image_basic_init (assemblyb);
- assembly = mb->dynamic_image;
-
- assembly->pe_kind = assemblyb->pe_kind;
- assembly->machine = assemblyb->machine;
- ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
- ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
-
- if (!mono_image_build_metadata (mb, error))
- return FALSE;
-
-
- if (mb->is_main && assemblyb->resources) {
- int len = mono_array_length (assemblyb->resources);
- for (i = 0; i < len; ++i) {
- if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
- return FALSE;
- }
- }
-
- if (mb->resources) {
- int len = mono_array_length (mb->resources);
- for (i = 0; i < len; ++i) {
- if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
- return FALSE;
- }
- }
-
- if (!build_compressed_metadata (assembly, error))
- return FALSE;
-
- if (mb->is_main)
- assembly_add_win32_resources (assembly, assemblyb);
-
- nsections = calc_section_size (assembly);
-
- /* The DOS header and stub */
- g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
- mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
-
- /* the dotnet header */
- header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
-
- /* the section tables */
- section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
-
- file_offset = section_start + sizeof (MonoSectionTable) * nsections;
- virtual_offset = VIRT_ALIGN;
- image_size = 0;
-
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- if (!assembly->sections [i].size)
- continue;
- /* align offsets */
- file_offset += FILE_ALIGN - 1;
- file_offset &= ~(FILE_ALIGN - 1);
- virtual_offset += VIRT_ALIGN - 1;
- virtual_offset &= ~(VIRT_ALIGN - 1);
-
- assembly->sections [i].offset = file_offset;
- assembly->sections [i].rva = virtual_offset;
-
- file_offset += assembly->sections [i].size;
- virtual_offset += assembly->sections [i].size;
- image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
- }
-
- file_offset += FILE_ALIGN - 1;
- file_offset &= ~(FILE_ALIGN - 1);
-
- image_size += section_start + sizeof (MonoSectionTable) * nsections;
-
- /* back-patch info */
- msdos = (MonoMSDOSHeader*)pefile->data;
- msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
-
- header = (MonoDotNetHeader*)(pefile->data + header_start);
- header->pesig [0] = 'P';
- header->pesig [1] = 'E';
-
- header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
- header->coff.coff_sections = GUINT16_FROM_LE (nsections);
- header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
- header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
- if (assemblyb->pekind == 1) {
- /* it's a dll */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
- } else {
- /* it's an exe */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
- }
-
- virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
-
- header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
- header->pe.pe_major = 6;
- header->pe.pe_minor = 0;
- size = assembly->sections [MONO_SECTION_TEXT].size;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->pe.pe_code_size = GUINT32_FROM_LE(size);
- size = assembly->sections [MONO_SECTION_RSRC].size;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->pe.pe_data_size = GUINT32_FROM_LE(size);
- g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
- header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
- header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
- /* pe_rva_entry_point always at the beginning of the text section */
- header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
-
- header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
- header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
- header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
- header->nt.pe_os_major = GUINT16_FROM_LE (4);
- header->nt.pe_os_minor = GUINT16_FROM_LE (0);
- header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
- size = section_start;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->nt.pe_header_size = GUINT32_FROM_LE (size);
- size = image_size;
- size += VIRT_ALIGN - 1;
- size &= ~(VIRT_ALIGN - 1);
- header->nt.pe_image_size = GUINT32_FROM_LE (size);
-
- /*
- // Translate the PEFileKind value to the value expected by the Windows loader
- */
- {
- short kind;
-
- /*
- // PEFileKinds.Dll == 1
- // PEFileKinds.ConsoleApplication == 2
- // PEFileKinds.WindowApplication == 3
- //
- // need to get:
- // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
- // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
- */
- if (assemblyb->pekind == 3)
- kind = 2;
- else
- kind = 3;
-
- header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
- }
- header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
- header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
- header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
- header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
- header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
- header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
-
- /* fill data directory entries */
-
- header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
- header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
-
- header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
- header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
-
- header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
- header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
- header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
- header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
- /* patch entrypoint name */
- if (assemblyb->pekind == 1)
- memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
- else
- memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
- /* patch imported function RVA name */
- rva = (guint32*)(assembly->code.data + assembly->iat_offset);
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
-
- /* the import table */
- header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
- header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
- /* patch imported dll RVA name and other entries in the dir */
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
-
- p = (guchar*)(assembly->code.data + assembly->ilt_offset);
- value = (assembly->text_rva + assembly->imp_names_offset);
- *p++ = (value) & 0xff;
- *p++ = (value >> 8) & (0xff);
- *p++ = (value >> 16) & (0xff);
- *p++ = (value >> 24) & (0xff);
-
- /* the CLI header info */
- cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
- cli_header->ch_size = GUINT32_FROM_LE (72);
- cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
- cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
- cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
- if (assemblyb->entry_point) {
- guint32 table_idx = 0;
- if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
- MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
- table_idx = methodb->table_idx;
- } else {
- table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
- }
- cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
- } else {
- cli_header->ch_entry_point = GUINT32_FROM_LE (0);
- }
- /* The embedded managed resources */
- text_offset = assembly->text_rva + assembly->code.index;
- cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
- text_offset += assembly->resources.index;
- cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
- text_offset += assembly->meta_size;
- if (assembly->strong_name_size) {
- cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
- text_offset += assembly->strong_name_size;
- }
-
- /* write the section tables and section content */
- section = (MonoSectionTable*)(pefile->data + section_start);
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- static const char section_names [][7] = {
- ".text", ".rsrc", ".reloc"
- };
- if (!assembly->sections [i].size)
- continue;
- strcpy (section->st_name, section_names [i]);
- /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
- section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
- section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
- section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
- section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
- section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
- section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
- section ++;
- }
-
- checked_write_file (file, pefile->data, pefile->index);
-
- mono_dynamic_stream_reset (pefile);
-
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- if (!assembly->sections [i].size)
- continue;
-
- if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
-
- switch (i) {
- case MONO_SECTION_TEXT:
- /* patch entry point */
- p = (guchar*)(assembly->code.data + 2);
- value = (virtual_base + assembly->text_rva + assembly->iat_offset);
- *p++ = (value) & 0xff;
- *p++ = (value >> 8) & 0xff;
- *p++ = (value >> 16) & 0xff;
- *p++ = (value >> 24) & 0xff;
-
- checked_write_file (file, assembly->code.data, assembly->code.index);
- checked_write_file (file, assembly->resources.data, assembly->resources.index);
- checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
- checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
-
-
- g_free (assembly->image.raw_metadata);
- break;
- case MONO_SECTION_RELOC: {
- struct {
- guint32 page_rva;
- guint32 block_size;
- guint16 type_and_offset;
- guint16 term;
- } reloc;
-
- g_assert (sizeof (reloc) == 12);
-
- reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
- reloc.block_size = GUINT32_FROM_LE (12);
-
- /*
- * the entrypoint is always at the start of the text section
- * 3 is IMAGE_REL_BASED_HIGHLOW
- * 2 is patch_size_rva - text_rva
- */
- reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
- reloc.term = 0;
-
- checked_write_file (file, &reloc, sizeof (reloc));
-
- break;
- }
- case MONO_SECTION_RSRC:
- if (assembly->win32_res) {
-
- /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
- fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
- checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
- }
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
- /* check that the file is properly padded */
- if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
- if (! SetEndOfFile (file))
- g_error ("SetEndOfFile returned %d\n", GetLastError ());
-
- mono_dynamic_stream_reset (&assembly->code);
- mono_dynamic_stream_reset (&assembly->us);
- mono_dynamic_stream_reset (&assembly->blob);
- mono_dynamic_stream_reset (&assembly->guid);
- mono_dynamic_stream_reset (&assembly->sheap);
-
- g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
- g_hash_table_destroy (assembly->blob_cache);
- assembly->blob_cache = NULL;
-
- return TRUE;
-}
-
-#else /* DISABLE_REFLECTION_EMIT_SAVE */
-
-gboolean
-mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
-{
- g_assert_not_reached ();
-}
-
-#endif /* DISABLE_REFLECTION_EMIT_SAVE */
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-MonoReflectionModule *
-mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
-{
- char *name;
- MonoImage *image;
- MonoImageOpenStatus status;
- MonoDynamicAssembly *assembly;
- guint32 module_count;
- MonoImage **new_modules;
- gboolean *new_modules_loaded;
-
- mono_error_init (error);
-
- name = mono_string_to_utf8_checked (fileName, error);
- return_val_if_nok (error, NULL);
-
- image = mono_image_open (name, &status);
- if (!image) {
- if (status == MONO_IMAGE_ERROR_ERRNO)
- mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
- else
- mono_error_set_bad_image_name (error, name, NULL);
- g_free (name);
- return NULL;
- }
-
- g_free (name);
-
- assembly = ab->dynamic_assembly;
- image->assembly = (MonoAssembly*)assembly;
-
- module_count = image->assembly->image->module_count;
- new_modules = g_new0 (MonoImage *, module_count + 1);
- new_modules_loaded = g_new0 (gboolean, module_count + 1);
-
- if (image->assembly->image->modules)
- memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
- if (image->assembly->image->modules_loaded)
- memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
- new_modules [module_count] = image;
- new_modules_loaded [module_count] = TRUE;
- mono_image_addref (image);
-
- g_free (image->assembly->image->modules);
- image->assembly->image->modules = new_modules;
- image->assembly->image->modules_loaded = new_modules_loaded;
- image->assembly->image->module_count ++;
-
- mono_assembly_load_references (image, &status);
- if (status) {
- mono_image_close (image);
- mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
- return NULL;
- }
-
- return mono_module_get_object_checked (mono_domain_get (), image, error);
-}
-
-#endif /* DISABLE_REFLECTION_EMIT */
-
-/*
- * We need to return always the same object for MethodInfo, FieldInfo etc..
- * but we need to consider the reflected type.
- * type uses a different hash, since it uses custom hash/equal functions.
- */
-
-typedef struct {
- gpointer item;
- MonoClass *refclass;
-} ReflectedEntry;
-
-static gboolean
-reflected_equal (gconstpointer a, gconstpointer b) {
- const ReflectedEntry *ea = (const ReflectedEntry *)a;
- const ReflectedEntry *eb = (const ReflectedEntry *)b;
-
- return (ea->item == eb->item) && (ea->refclass == eb->refclass);
-}
-
-static guint
-reflected_hash (gconstpointer a) {
- const ReflectedEntry *ea = (const ReflectedEntry *)a;
- return mono_aligned_addr_hash (ea->item);
-}
-
-#define CHECK_OBJECT(t,p,k) \
- do { \
- t _obj; \
- ReflectedEntry e; \
- e.item = (p); \
- e.refclass = (k); \
- mono_domain_lock (domain); \
- if (!domain->refobject_hash) \
- domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
- if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
- mono_domain_unlock (domain); \
- return _obj; \
- } \
- mono_domain_unlock (domain); \
- } while (0)
-
-#ifdef HAVE_BOEHM_GC
-/* ReflectedEntry doesn't need to be GC tracked */
-#define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
-#define FREE_REFENTRY(entry) g_free ((entry))
-#define REFENTRY_REQUIRES_CLEANUP
-#else
-#define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
-/* FIXME: */
-#define FREE_REFENTRY(entry)
-#endif
-
-#define CACHE_OBJECT(t,p,o,k) \
- do { \
- t _obj; \
- ReflectedEntry pe; \
- pe.item = (p); \
- pe.refclass = (k); \
- mono_domain_lock (domain); \
- if (!domain->refobject_hash) \
- domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
- _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
- if (!_obj) { \
- ReflectedEntry *e = ALLOC_REFENTRY; \
- e->item = (p); \
- e->refclass = (k); \
- mono_g_hash_table_insert (domain->refobject_hash, e,o); \
- _obj = o; \
- } \
- mono_domain_unlock (domain); \
- return _obj; \
- } while (0)
-
-static void
-clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
-{
- mono_domain_lock (domain);
- if (domain->refobject_hash) {
- ReflectedEntry pe;
- gpointer orig_pe, orig_value;
-
- pe.item = o;
- pe.refclass = klass;
- if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
- mono_g_hash_table_remove (domain->refobject_hash, &pe);
- FREE_REFENTRY (orig_pe);
- }
- }
- mono_domain_unlock (domain);
-}
-
-#ifdef REFENTRY_REQUIRES_CLEANUP
-static void
-cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
-{
- FREE_REFENTRY (key);
-}
-#endif
-
-void
-mono_reflection_cleanup_domain (MonoDomain *domain)
-{
- if (domain->refobject_hash) {
-/*let's avoid scanning the whole hashtable if not needed*/
-#ifdef REFENTRY_REQUIRES_CLEANUP
- mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
-#endif
- mono_g_hash_table_destroy (domain->refobject_hash);
- domain->refobject_hash = NULL;
- }
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static gpointer
-register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
-{
- CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
-}
-
-static gpointer
-register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
-{
- CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
-}
-
-static gboolean
-image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicImage *image = moduleb->dynamic_image;
- MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
- mono_error_init (error);
- if (!image) {
- int module_count;
- MonoImage **new_modules;
- MonoImage *ass;
- char *name, *fqname;
- /*
- * FIXME: we already created an image in mono_image_basic_init (), but
- * we don't know which module it belongs to, since that is only
- * determined at assembly save time.
- */
- /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
- name = mono_string_to_utf8_checked (ab->name, error);
- return_val_if_nok (error, FALSE);
- fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
- if (!is_ok (error)) {
- g_free (name);
- return FALSE;
- }
- image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
-
- moduleb->module.image = &image->image;
- moduleb->dynamic_image = image;
- register_module (mono_object_domain (moduleb), moduleb, image);
-
- /* register the module with the assembly */
- ass = ab->dynamic_assembly->assembly.image;
- module_count = ass->module_count;
- new_modules = g_new0 (MonoImage *, module_count + 1);
-
- if (ass->modules)
- memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
- new_modules [module_count] = &image->image;
- mono_image_addref (&image->image);
-
- g_free (ass->modules);
- ass->modules = new_modules;
- ass->module_count ++;
- }
- return TRUE;
-}
-
-static void
-mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
-{
- MonoError error;
- (void) image_module_basic_init (moduleb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-#endif
-
-/*
- * mono_assembly_get_object:
- * @domain: an app domain
- * @assembly: an assembly
- *
- * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
- */
-MonoReflectionAssembly*
-mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
-{
- MonoError error;
- MonoReflectionAssembly *result;
- result = mono_assembly_get_object_checked (domain, assembly, &error);
- mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
- return result;
-}
-/*
- * mono_assembly_get_object_checked:
- * @domain: an app domain
- * @assembly: an assembly
- *
- * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
- */
-MonoReflectionAssembly*
-mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
-{
- MonoReflectionAssembly *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
- res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
- if (!res)
- return NULL;
- res->assembly = assembly;
-
- CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
-}
-
-
-
-MonoReflectionModule*
-mono_module_get_object (MonoDomain *domain, MonoImage *image)
-{
- MonoError error;
- MonoReflectionModule *result;
- result = mono_module_get_object_checked (domain, image, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoReflectionModule*
-mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
-{
- MonoReflectionModule *res;
- char* basename;
-
- mono_error_init (error);
- CHECK_OBJECT (MonoReflectionModule *, image, NULL);
- res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
- if (!res)
- return NULL;
-
- res->image = image;
- MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
- if (!assm_obj)
- return NULL;
- MONO_OBJECT_SETREF (res, assembly, assm_obj);
-
- MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
- basename = g_path_get_basename (image->name);
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
- MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
-
- g_free (basename);
-
- if (image->assembly->image == image) {
- res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
- } else {
- int i;
- res->token = 0;
- if (image->assembly->image->modules) {
- for (i = 0; i < image->assembly->image->module_count; i++) {
- if (image->assembly->image->modules [i] == image)
- res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
- }
- g_assert (res->token);
- }
- }
-
- CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
-}
-
-MonoReflectionModule*
-mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
-{
- MonoError error;
- MonoReflectionModule *result;
- result = mono_module_file_get_object_checked (domain, image, table_index, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoReflectionModule*
-mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
-{
- MonoReflectionModule *res;
- MonoTableInfo *table;
- guint32 cols [MONO_FILE_SIZE];
- const char *name;
- guint32 i, name_idx;
- const char *val;
-
- mono_error_init (error);
-
- res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
- if (!res)
- return NULL;
-
- table = &image->tables [MONO_TABLE_FILE];
- g_assert (table_index < table->rows);
- mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
-
- res->image = NULL;
- MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
- if (!assm_obj)
- return NULL;
- MONO_OBJECT_SETREF (res, assembly, assm_obj);
- name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
-
- /* Check whenever the row has a corresponding row in the moduleref table */
- table = &image->tables [MONO_TABLE_MODULEREF];
- for (i = 0; i < table->rows; ++i) {
- name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
- val = mono_metadata_string_heap (image, name_idx);
- if (strcmp (val, name) == 0)
- res->image = image->modules [i];
- }
-
- MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
- MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
- res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
- res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
-
- return res;
-}
-
-static gboolean
-verify_safe_for_managed_space (MonoType *type)
-{
- switch (type->type) {
-#ifdef DEBUG_HARDER
- case MONO_TYPE_ARRAY:
- return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
- case MONO_TYPE_PTR:
- return verify_safe_for_managed_space (type->data.type);
- case MONO_TYPE_SZARRAY:
- return verify_safe_for_managed_space (&type->data.klass->byval_arg);
- case MONO_TYPE_GENERICINST: {
- MonoGenericInst *inst = type->data.generic_class->inst;
- int i;
- if (!inst->is_open)
- break;
- for (i = 0; i < inst->type_argc; ++i)
- if (!verify_safe_for_managed_space (inst->type_argv [i]))
- return FALSE;
- return TRUE;
- }
-#endif
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- return TRUE;
- default:
- return TRUE;
- }
-}
-
-static MonoType*
-mono_type_normalize (MonoType *type)
-{
- int i;
- MonoGenericClass *gclass;
- MonoGenericInst *ginst;
- MonoClass *gtd;
- MonoGenericContainer *gcontainer;
- MonoType **argv = NULL;
- gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
-
- if (type->type != MONO_TYPE_GENERICINST)
- return type;
-
- gclass = type->data.generic_class;
- ginst = gclass->context.class_inst;
- if (!ginst->is_open)
- return type;
-
- gtd = gclass->container_class;
- gcontainer = gtd->generic_container;
- argv = g_newa (MonoType*, ginst->type_argc);
-
- for (i = 0; i < ginst->type_argc; ++i) {
- MonoType *t = ginst->type_argv [i], *norm;
- if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
- is_denorm_gtd = FALSE;
- norm = mono_type_normalize (t);
- argv [i] = norm;
- if (norm != t)
- requires_rebind = TRUE;
- }
-
- if (is_denorm_gtd)
- return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
-
- if (requires_rebind) {
- MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
- return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
- }
-
- return type;
-}
-/*
- * mono_type_get_object:
- * @domain: an app domain
- * @type: a type
- *
- * Return an System.MonoType object representing the type @type.
- */
-MonoReflectionType*
-mono_type_get_object (MonoDomain *domain, MonoType *type)
-{
- MonoError error;
- MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
- mono_error_cleanup (&error);
-
- return ret;
-}
-
-MonoReflectionType*
-mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
-{
- MonoType *norm_type;
- MonoReflectionType *res;
- MonoClass *klass;
-
- mono_error_init (error);
-
- klass = mono_class_from_mono_type (type);
-
- /*we must avoid using @type as it might have come
- * from a mono_metadata_type_dup and the caller
- * expects that is can be freed.
- * Using the right type from
- */
- type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
-
- /* void is very common */
- if (type->type == MONO_TYPE_VOID && domain->typeof_void)
- return (MonoReflectionType*)domain->typeof_void;
-
- /*
- * If the vtable of the given class was already created, we can use
- * the MonoType from there and avoid all locking and hash table lookups.
- *
- * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
- * that the resulting object is different.
- */
- if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
- MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
- if (vtable && vtable->type)
- return (MonoReflectionType *)vtable->type;
- }
-
- mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
- mono_domain_lock (domain);
- if (!domain->type_hash)
- domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
- (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
- if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
- }
-
- /*Types must be normalized so a generic instance of the GTD get's the same inner type.
- * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
- * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
- * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
- * artifact of how generics are encoded and should be transparent to managed code so we
- * need to weed out this diference when retrieving managed System.Type objects.
- */
- norm_type = mono_type_normalize (type);
- if (norm_type != type) {
- res = mono_type_get_object_checked (domain, norm_type, error);
- if (!mono_error_ok (error))
- return NULL;
- mono_g_hash_table_insert (domain->type_hash, type, res);
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
- }
-
- /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
- if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
- g_assert (0);
-
- if (!verify_safe_for_managed_space (type)) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
- return NULL;
- }
-
- if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
- gboolean is_type_done = TRUE;
- /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
- * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
- * We can't simply close the types as this will interfere with other parts of the generics machinery.
- */
- if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
- MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
-
- if (gparam->owner && gparam->owner->is_method) {
- MonoMethod *method = gparam->owner->owner.method;
- if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
- is_type_done = FALSE;
- } else if (gparam->owner && !gparam->owner->is_method) {
- MonoClass *klass = gparam->owner->owner.klass;
- if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
- is_type_done = FALSE;
- }
- }
-
- /* g_assert_not_reached (); */
- /* should this be considered an error condition? */
- if (is_type_done && !type->byref) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return (MonoReflectionType *)mono_class_get_ref_info (klass);
- }
- }
- /* This is stored in vtables/JITted code so it has to be pinned */
- res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
- if (!mono_error_ok (error))
- return NULL;
-
- res->type = type;
- mono_g_hash_table_insert (domain->type_hash, type, res);
-
- if (type->type == MONO_TYPE_VOID)
- domain->typeof_void = (MonoObject*)res;
-
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
-}
-
-/*
- * mono_method_get_object:
- * @domain: an app domain
- * @method: a method
- * @refclass: the reflected type (can be NULL)
- *
- * Return an System.Reflection.MonoMethod object representing the method @method.
- */
-MonoReflectionMethod*
-mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
-{
- MonoError error;
- MonoReflectionMethod *ret = NULL;
- ret = mono_method_get_object_checked (domain, method, refclass, &error);
- mono_error_cleanup (&error);
- return ret;
-}
-
-/*
- * mono_method_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @refclass: the reflected type (can be NULL)
- * @error: set on error.
- *
- * Return an System.Reflection.MonoMethod object representing the method @method.
- * Returns NULL and sets @error on error.
- */
-MonoReflectionMethod*
-mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
-{
- /*
- * We use the same C representation for methods and constructors, but the type
- * name in C# is different.
- */
- MonoReflectionType *rt;
- MonoClass *klass;
- MonoReflectionMethod *ret;
-
- mono_error_init (error);
-
- if (method->is_inflated) {
- MonoReflectionGenericMethod *gret;
-
- if (!refclass)
- refclass = method->klass;
- CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
- if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
- klass = mono_class_get_mono_generic_cmethod_class ();
- } else {
- klass = mono_class_get_mono_generic_method_class ();
- }
- gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
- if (!mono_error_ok (error))
- goto leave;
- gret->method.method = method;
-
- MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
-
- rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
- if (!mono_error_ok (error))
- goto leave;
-
- MONO_OBJECT_SETREF (gret, method.reftype, rt);
-
- CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
- }
-
- if (!refclass)
- refclass = method->klass;
-
- CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
- if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
- klass = mono_class_get_mono_cmethod_class ();
- }
- else {
- klass = mono_class_get_mono_method_class ();
- }
- ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
- if (!mono_error_ok (error))
- goto leave;
- ret->method = method;
-
- rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
- if (!mono_error_ok (error))
- goto leave;
-
- MONO_OBJECT_SETREF (ret, reftype, rt);
-
- CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
-
-leave:
- g_assert (!mono_error_ok (error));
- return NULL;
-}
-
-/*
- * mono_method_clear_object:
- *
- * Clear the cached reflection objects for the dynamic method METHOD.
- */
-void
-mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
-{
- MonoClass *klass;
- g_assert (method_is_dynamic (method));
-
- klass = method->klass;
- while (klass) {
- clear_cached_object (domain, method, klass);
- klass = klass->parent;
- }
- /* Added by mono_param_get_objects () */
- clear_cached_object (domain, &(method->signature), NULL);
- klass = method->klass;
- while (klass) {
- clear_cached_object (domain, &(method->signature), klass);
- klass = klass->parent;
- }
-}
-
-/*
- * mono_field_get_object:
- * @domain: an app domain
- * @klass: a type
- * @field: a field
- *
- * Return an System.Reflection.MonoField object representing the field @field
- * in class @klass.
- */
-MonoReflectionField*
-mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
-{
- MonoError error;
- MonoReflectionField *result;
- result = mono_field_get_object_checked (domain, klass, field, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/*
- * mono_field_get_object_checked:
- * @domain: an app domain
- * @klass: a type
- * @field: a field
- * @error: set on error
- *
- * Return an System.Reflection.MonoField object representing the field @field
- * in class @klass. On error, returns NULL and sets @error.
- */
-MonoReflectionField*
-mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
-{
- MonoReflectionType *rt;
- MonoReflectionField *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionField *, field, klass);
- res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
- if (!res)
- return NULL;
- res->klass = klass;
- res->field = field;
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
-
- if (is_field_on_inst (field)) {
- res->attrs = get_field_on_inst_generic_type (field)->attrs;
-
- rt = mono_type_get_object_checked (domain, field->type, error);
- if (!mono_error_ok (error))
- return NULL;
-
- MONO_OBJECT_SETREF (res, type, rt);
- } else {
- if (field->type) {
- rt = mono_type_get_object_checked (domain, field->type, error);
- if (!mono_error_ok (error))
- return NULL;
-
- MONO_OBJECT_SETREF (res, type, rt);
- }
- res->attrs = mono_field_get_flags (field);
- }
- CACHE_OBJECT (MonoReflectionField *, field, res, klass);
-}
-
-/*
- * mono_property_get_object:
- * @domain: an app domain
- * @klass: a type
- * @property: a property
- *
- * Return an System.Reflection.MonoProperty object representing the property @property
- * in class @klass.
- */
-MonoReflectionProperty*
-mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
-{
- MonoError error;
- MonoReflectionProperty *result;
- result = mono_property_get_object_checked (domain, klass, property, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_property_get_object:
- * @domain: an app domain
- * @klass: a type
- * @property: a property
- * @error: set on error
- *
- * Return an System.Reflection.MonoProperty object representing the property @property
- * in class @klass. On error returns NULL and sets @error.
- */
-MonoReflectionProperty*
-mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
-{
- MonoReflectionProperty *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionProperty *, property, klass);
- res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
- if (!res)
- return NULL;
- res->klass = klass;
- res->property = property;
- CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
-}
-
-/*
- * mono_event_get_object:
- * @domain: an app domain
- * @klass: a type
- * @event: a event
- *
- * Return an System.Reflection.MonoEvent object representing the event @event
- * in class @klass.
- */
-MonoReflectionEvent*
-mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
-{
- MonoError error;
- MonoReflectionEvent *result;
- result = mono_event_get_object_checked (domain, klass, event, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_event_get_object_checked:
- * @domain: an app domain
- * @klass: a type
- * @event: a event
- * @error: set on error
- *
- * Return an System.Reflection.MonoEvent object representing the event @event
- * in class @klass. On failure sets @error and returns NULL
- */
-MonoReflectionEvent*
-mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
-{
- MonoReflectionEvent *res;
- MonoReflectionMonoEvent *mono_event;
-
- mono_error_init (error);
- CHECK_OBJECT (MonoReflectionEvent *, event, klass);
- mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
- if (!mono_event)
- return NULL;
- mono_event->klass = klass;
- mono_event->event = event;
- res = (MonoReflectionEvent*)mono_event;
- CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
-}
-
-/**
- * mono_get_reflection_missing_object:
- * @domain: Domain where the object lives
- *
- * Returns the System.Reflection.Missing.Value singleton object
- * (of type System.Reflection.Missing).
- *
- * Used as the value for ParameterInfo.DefaultValue when Optional
- * is present
- */
-static MonoObject *
-mono_get_reflection_missing_object (MonoDomain *domain)
-{
- MonoError error;
- MonoObject *obj;
- static MonoClassField *missing_value_field = NULL;
-
- if (!missing_value_field) {
- MonoClass *missing_klass;
- missing_klass = mono_class_get_missing_class ();
- mono_class_init (missing_klass);
- missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
- g_assert (missing_value_field);
- }
- obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
- mono_error_assert_ok (&error);
- return obj;
-}
-
-static MonoObject*
-get_dbnull (MonoDomain *domain, MonoObject **dbnull)
-{
- if (!*dbnull)
- *dbnull = mono_get_dbnull_object (domain);
- return *dbnull;
-}
-
-static MonoObject*
-get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
-{
- if (!*reflection_missing)
- *reflection_missing = mono_get_reflection_missing_object (domain);
- return *reflection_missing;
-}
-
-/*
- * mono_param_get_objects:
- * @domain: an app domain
- * @method: a method
- *
- * Return an System.Reflection.ParameterInfo array object representing the parameters
- * in the method @method.
- */
-MonoArray*
-mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
-{
- static MonoClass *System_Reflection_ParameterInfo;
- static MonoClass *System_Reflection_ParameterInfo_array;
- MonoArray *res = NULL;
- MonoReflectionMethod *member = NULL;
- MonoReflectionParameter *param = NULL;
- char **names = NULL, **blobs = NULL;
- guint32 *types = NULL;
- MonoType *type = NULL;
- MonoObject *dbnull = NULL;
- MonoObject *missing = NULL;
- MonoMarshalSpec **mspecs = NULL;
- MonoMethodSignature *sig = NULL;
- MonoVTable *pinfo_vtable;
- MonoReflectionType *rt;
- int i;
-
- mono_error_init (error);
-
- if (!System_Reflection_ParameterInfo_array) {
- MonoClass *klass;
-
- klass = mono_class_get_mono_parameter_info_class ();
-
- mono_memory_barrier ();
- System_Reflection_ParameterInfo = klass;
-
-
- klass = mono_array_class_get (klass, 1);
- mono_memory_barrier ();
- System_Reflection_ParameterInfo_array = klass;
- }
-
- sig = mono_method_signature_checked (method, error);
- if (!mono_error_ok (error))
- goto leave;
-
- if (!sig->param_count) {
- res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
- if (!res)
- goto leave;
-
- return res;
- }
-
- /* Note: the cache is based on the address of the signature into the method
- * since we already cache MethodInfos with the method as keys.
- */
- CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
-
- member = mono_method_get_object_checked (domain, method, refclass, error);
- if (!member)
- goto leave;
- names = g_new (char *, sig->param_count);
- mono_method_get_param_names (method, (const char **) names);
-
- mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
- mono_method_get_marshal_info (method, mspecs);
-
- res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
- if (!res)
- goto leave;
-
- pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
- for (i = 0; i < sig->param_count; ++i) {
- param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
- if (!param)
- goto leave;
-
- rt = mono_type_get_object_checked (domain, sig->params [i], error);
- if (!rt)
- goto leave;
-
- MONO_OBJECT_SETREF (param, ClassImpl, rt);
-
- MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
-
- MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
-
- param->PositionImpl = i;
- param->AttrsImpl = sig->params [i]->attrs;
-
- if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
- if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
- else
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
- } else {
-
- if (!blobs) {
- blobs = g_new0 (char *, sig->param_count);
- types = g_new0 (guint32, sig->param_count);
- get_default_param_value_blobs (method, blobs, types);
- }
-
- /* Build MonoType for the type from the Constant Table */
- if (!type)
- type = g_new0 (MonoType, 1);
- type->type = (MonoTypeEnum)types [i];
- type->data.klass = NULL;
- if (types [i] == MONO_TYPE_CLASS)
- type->data.klass = mono_defaults.object_class;
- else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
- /* For enums, types [i] contains the base type */
-
- type->type = MONO_TYPE_VALUETYPE;
- type->data.klass = mono_class_from_mono_type (sig->params [i]);
- } else
- type->data.klass = mono_class_from_mono_type (type);
-
- MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
- if (!is_ok (error))
- goto leave;
- MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
-
- /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
- if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
- if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
- else
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
- }
-
- }
-
- if (mspecs [i + 1]) {
- MonoReflectionMarshalAsAttribute* mobj;
- mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
- if (!mobj)
- goto leave;
- MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
- }
-
- mono_array_setref (res, i, param);
- }
-
-leave:
- g_free (names);
- g_free (blobs);
- g_free (types);
- g_free (type);
-
- if (sig) {
- for (i = sig->param_count; i >= 0; i--) {
- if (mspecs [i])
- mono_metadata_free_marshal_spec (mspecs [i]);
- }
- }
- g_free (mspecs);
-
- if (!is_ok (error))
- return NULL;
-
- CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
-}
-
-MonoArray*
-mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
-{
- MonoError error;
- MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/*
- * mono_method_body_get_object:
- * @domain: an app domain
- * @method: a method
- *
- * Return an System.Reflection.MethodBody object representing the method @method.
- */
-MonoReflectionMethodBody*
-mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
-{
- MonoError error;
- MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_method_body_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @error: set on error
- *
- * Return an System.Reflection.MethodBody object representing the
- * method @method. On failure, returns NULL and sets @error.
- */
-MonoReflectionMethodBody*
-mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
-{
- MonoReflectionMethodBody *ret;
- MonoMethodHeader *header;
- MonoImage *image;
- MonoReflectionType *rt;
- guint32 method_rva, local_var_sig_token;
- char *ptr;
- unsigned char format, flags;
- int i;
-
- mono_error_init (error);
-
- /* for compatibility with .net */
- if (method_is_dynamic (method)) {
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
- return NULL;
- }
-
- CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
-
- if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
- (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
- (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
- (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
- return NULL;
-
- image = method->klass->image;
- header = mono_method_get_header_checked (method, error);
- return_val_if_nok (error, NULL);
-
- if (!image_is_dynamic (image)) {
- /* Obtain local vars signature token */
- method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
- ptr = mono_image_rva_map (image, method_rva);
- flags = *(const unsigned char *) ptr;
- format = flags & METHOD_HEADER_FORMAT_MASK;
- switch (format){
- case METHOD_HEADER_TINY_FORMAT:
- local_var_sig_token = 0;
- break;
- case METHOD_HEADER_FAT_FORMAT:
- ptr += 2;
- ptr += 2;
- ptr += 4;
- local_var_sig_token = read32 (ptr);
- break;
- default:
- g_assert_not_reached ();
- }
- } else
- local_var_sig_token = 0; //FIXME
-
- ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
- if (!is_ok (error))
- goto fail;
-
- ret->init_locals = header->init_locals;
- ret->max_stack = header->max_stack;
- ret->local_var_sig_token = local_var_sig_token;
- MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, il, il_arr);
- memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
-
- /* Locals */
- MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, locals, locals_arr);
- for (i = 0; i < header->num_locals; ++i) {
- MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
- if (!is_ok (error))
- goto fail;
-
- rt = mono_type_get_object_checked (domain, header->locals [i], error);
- if (!is_ok (error))
- goto fail;
-
- MONO_OBJECT_SETREF (info, local_type, rt);
-
- info->is_pinned = header->locals [i]->pinned;
- info->local_index = i;
- mono_array_setref (ret->locals, i, info);
- }
-
- /* Exceptions */
- MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
- for (i = 0; i < header->num_clauses; ++i) {
- MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
- if (!is_ok (error))
- goto fail;
- MonoExceptionClause *clause = &header->clauses [i];
-
- info->flags = clause->flags;
- info->try_offset = clause->try_offset;
- info->try_length = clause->try_len;
- info->handler_offset = clause->handler_offset;
- info->handler_length = clause->handler_len;
- if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
- info->filter_offset = clause->data.filter_offset;
- else if (clause->data.catch_class) {
- rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
- if (!is_ok (error))
- goto fail;
-
- MONO_OBJECT_SETREF (info, catch_type, rt);
- }
-
- mono_array_setref (ret->clauses, i, info);
- }
-
- mono_metadata_free_mh (header);
- CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
- return ret;
-
-fail:
- mono_metadata_free_mh (header);
- return NULL;
-}
-
-/**
- * mono_get_dbnull_object:
- * @domain: Domain where the object lives
- *
- * Returns the System.DBNull.Value singleton object
- *
- * Used as the value for ParameterInfo.DefaultValue
- */
-MonoObject *
-mono_get_dbnull_object (MonoDomain *domain)
-{
- MonoError error;
- MonoObject *obj;
- static MonoClassField *dbnull_value_field = NULL;
-
- if (!dbnull_value_field) {
- MonoClass *dbnull_klass;
- dbnull_klass = mono_class_get_dbnull_class ();
- dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
- g_assert (dbnull_value_field);
- }
- obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
- mono_error_assert_ok (&error);
- return obj;
-}
-
-static void
-get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
-{
- guint32 param_index, i, lastp, crow = 0;
- guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
- gint32 idx;
-
- MonoClass *klass = method->klass;
- MonoImage *image = klass->image;
- MonoMethodSignature *methodsig = mono_method_signature (method);
-
- MonoTableInfo *constt;
- MonoTableInfo *methodt;
- MonoTableInfo *paramt;
-
- if (!methodsig->param_count)
- return;
-
- mono_class_init (klass);
-
- if (image_is_dynamic (klass->image)) {
- MonoReflectionMethodAux *aux;
- if (method->is_inflated)
- method = ((MonoMethodInflated*)method)->declaring;
- aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
- if (aux && aux->param_defaults) {
- memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
- memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
- }
- return;
- }
-
- methodt = &klass->image->tables [MONO_TABLE_METHOD];
- paramt = &klass->image->tables [MONO_TABLE_PARAM];
- constt = &image->tables [MONO_TABLE_CONSTANT];
-
- idx = mono_method_get_index (method) - 1;
- g_assert (idx != -1);
-
- param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
- if (idx + 1 < methodt->rows)
- lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
- else
- lastp = paramt->rows + 1;
-
- for (i = param_index; i < lastp; ++i) {
- guint32 paramseq;
-
- mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
- paramseq = param_cols [MONO_PARAM_SEQUENCE];
-
- if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
- continue;
-
- crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
- if (!crow) {
- continue;
- }
-
- mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
- blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
- types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
- }
-
- return;
-}
-
-MonoObject *
-mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
-{
- void *retval;
- MonoClass *klass;
- MonoObject *object;
- MonoType *basetype = type;
-
- mono_error_init (error);
-
- if (!blob)
- return NULL;
-
- klass = mono_class_from_mono_type (type);
- if (klass->valuetype) {
- object = mono_object_new_checked (domain, klass, error);
- return_val_if_nok (error, NULL);
- retval = ((gchar *) object + sizeof (MonoObject));
- if (klass->enumtype)
- basetype = mono_class_enum_basetype (klass);
- } else {
- retval = &object;
- }
-
- if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
- return object;
- else
- return NULL;
-}
-
-static int
-assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
- int found_sep;
- char *s;
- gboolean quoted = FALSE;
-
- memset (assembly, 0, sizeof (MonoAssemblyName));
- assembly->culture = "";
- memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
-
- if (*p == '"') {
- quoted = TRUE;
- p++;
- }
- assembly->name = p;
- while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
- p++;
- if (quoted) {
- if (*p != '"')
- return 1;
- *p = 0;
- p++;
- }
- if (*p != ',')
- return 1;
- *p = 0;
- /* Remove trailing whitespace */
- s = p - 1;
- while (*s && g_ascii_isspace (*s))
- *s-- = 0;
- p ++;
- while (g_ascii_isspace (*p))
- p++;
- while (*p) {
- if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
- p += 8;
- assembly->major = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->minor = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->build = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->revision = strtoul (p, &s, 10);
- if (s == p)
- return 1;
- p = s;
- } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
- p += 8;
- if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
- assembly->culture = "";
- p += 7;
- } else {
- assembly->culture = p;
- while (*p && *p != ',') {
- p++;
- }
- }
- } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
- p += 15;
- if (strncmp (p, "null", 4) == 0) {
- p += 4;
- } else {
- int len;
- gchar *start = p;
- while (*p && *p != ',') {
- p++;
- }
- len = (p - start + 1);
- if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
- len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
- g_strlcpy ((char*)assembly->public_key_token, start, len);
- }
- } else {
- while (*p && *p != ',')
- p++;
- }
- found_sep = 0;
- while (g_ascii_isspace (*p) || *p == ',') {
- *p++ = 0;
- found_sep = 1;
- continue;
- }
- /* failed */
- if (!found_sep)
- return 1;
- }
-
- return 0;
-}
-
-/*
- * mono_reflection_parse_type:
- * @name: type name
- *
- * Parse a type name as accepted by the GetType () method and output the info
- * extracted in the info structure.
- * the name param will be mangled, so, make a copy before passing it to this function.
- * The fields in info will be valid until the memory pointed to by name is valid.
- *
- * See also mono_type_get_name () below.
- *
- * Returns: 0 on parse error.
- */
-static int
-_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
- MonoTypeNameParse *info)
-{
- char *start, *p, *w, *last_point, *startn;
- int in_modifiers = 0;
- int isbyref = 0, rank = 0, isptr = 0;
-
- start = p = w = name;
-
- //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
- memset (&info->assembly, 0, sizeof (MonoAssemblyName));
- info->name = info->name_space = NULL;
- info->nested = NULL;
- info->modifiers = NULL;
- info->type_arguments = NULL;
-
- /* last_point separates the namespace from the name */
- last_point = NULL;
- /* Skips spaces */
- while (*p == ' ') p++, start++, w++, name++;
-
- while (*p) {
- switch (*p) {
- case '+':
- *p = 0; /* NULL terminate the name */
- startn = p + 1;
- info->nested = g_list_append (info->nested, startn);
- /* we have parsed the nesting namespace + name */
- if (info->name)
- break;
- if (last_point) {
- info->name_space = start;
- *last_point = 0;
- info->name = last_point + 1;
- } else {
- info->name_space = (char *)"";
- info->name = start;
- }
- break;
- case '.':
- last_point = p;
- break;
- case '\\':
- ++p;
- break;
- case '&':
- case '*':
- case '[':
- case ',':
- case ']':
- in_modifiers = 1;
- break;
- default:
- break;
- }
- if (in_modifiers)
- break;
- // *w++ = *p++;
- p++;
- }
-
- if (!info->name) {
- if (last_point) {
- info->name_space = start;
- *last_point = 0;
- info->name = last_point + 1;
- } else {
- info->name_space = (char *)"";
- info->name = start;
- }
- }
- while (*p) {
- switch (*p) {
- case '&':
- if (isbyref) /* only one level allowed by the spec */
- return 0;
- isbyref = 1;
- isptr = 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
- *p++ = 0;
- break;
- case '*':
- if (isbyref) /* pointer to ref not okay */
- return 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
- isptr = 1;
- *p++ = 0;
- break;
- case '[':
- if (isbyref) /* array of ref and generic ref are not okay */
- return 0;
- //Decide if it's an array of a generic argument list
- *p++ = 0;
-
- if (!*p) //XXX test
- return 0;
- if (*p == ',' || *p == '*' || *p == ']') { //array
- isptr = 0;
- rank = 1;
- while (*p) {
- if (*p == ']')
- break;
- if (*p == ',')
- rank++;
- else if (*p == '*') /* '*' means unknown lower bound */
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
- else
- return 0;
- ++p;
- }
- if (*p++ != ']')
- return 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
- } else {
- if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
- return 0;
- isptr = 0;
- info->type_arguments = g_ptr_array_new ();
- while (*p) {
- MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
- gboolean fqname = FALSE;
-
- g_ptr_array_add (info->type_arguments, subinfo);
-
- while (*p == ' ') p++;
- if (*p == '[') {
- p++;
- fqname = TRUE;
- }
-
- if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
- return 0;
-
- /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
- if (fqname && (*p != ']')) {
- char *aname;
-
- if (*p != ',')
- return 0;
- *p++ = 0;
-
- aname = p;
- while (*p && (*p != ']'))
- p++;
-
- if (*p != ']')
- return 0;
-
- *p++ = 0;
- while (*aname) {
- if (g_ascii_isspace (*aname)) {
- ++aname;
- continue;
- }
- break;
- }
- if (!*aname ||
- !assembly_name_to_aname (&subinfo->assembly, aname))
- return 0;
- } else if (fqname && (*p == ']')) {
- *p++ = 0;
- }
- if (*p == ']') {
- *p++ = 0;
- break;
- } else if (!*p) {
- return 0;
- }
- *p++ = 0;
- }
- }
- break;
- case ']':
- if (is_recursed)
- goto end;
- return 0;
- case ',':
- if (is_recursed)
- goto end;
- *p++ = 0;
- while (*p) {
- if (g_ascii_isspace (*p)) {
- ++p;
- continue;
- }
- break;
- }
- if (!*p)
- return 0; /* missing assembly name */
- if (!assembly_name_to_aname (&info->assembly, p))
- return 0;
- break;
- default:
- return 0;
- }
- if (info->assembly.name)
- break;
- }
- // *w = 0; /* terminate class name */
- end:
- if (!info->name || !*info->name)
- return 0;
- if (endptr)
- *endptr = p;
- /* add other consistency checks */
- return 1;
-}
-
-
-/**
- * mono_identifier_unescape_type_name_chars:
- * @identifier: the display name of a mono type
- *
- * Returns:
- * The name in internal form, that is without escaping backslashes.
- *
- * The string is modified in place!
- */
-char*
-mono_identifier_unescape_type_name_chars(char* identifier)
-{
- char *w, *r;
- if (!identifier)
- return NULL;
- for (w = r = identifier; *r != 0; r++)
- {
- char c = *r;
- if (c == '\\') {
- r++;
- if (*r == 0)
- break;
- c = *r;
- }
- *w = c;
- w++;
- }
- if (w != r)
- *w = 0;
- return identifier;
-}
-
-void
-mono_identifier_unescape_info (MonoTypeNameParse* info);
-
-static void
-unescape_each_type_argument(void* data, void* user_data)
-{
- MonoTypeNameParse* info = (MonoTypeNameParse*)data;
- mono_identifier_unescape_info (info);
-}
-
-static void
-unescape_each_nested_name (void* data, void* user_data)
-{
- char* nested_name = (char*) data;
- mono_identifier_unescape_type_name_chars(nested_name);
-}
-
-/**
- * mono_identifier_unescape_info:
- *
- * @info: a parsed display form of an (optionally assembly qualified) full type name.
- *
- * Returns: nothing.
- *
- * Destructively updates the info by unescaping the identifiers that
- * comprise the type namespace, name, nested types (if any) and
- * generic type arguments (if any).
- *
- * The resulting info has the names in internal form.
- *
- */
-void
-mono_identifier_unescape_info (MonoTypeNameParse *info)
-{
- if (!info)
- return;
- mono_identifier_unescape_type_name_chars(info->name_space);
- mono_identifier_unescape_type_name_chars(info->name);
- // but don't escape info->assembly
- if (info->type_arguments)
- g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
- if (info->nested)
- g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
-}
-
-int
-mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
-{
- int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
- if (ok) {
- mono_identifier_unescape_info (info);
- }
- return ok;
-}
-
-static MonoType*
-_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
-{
- gboolean type_resolve = FALSE;
- MonoType *type;
- MonoImage *rootimage = image;
-
- mono_error_init (error);
-
- if (info->assembly.name) {
- MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
- if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
- /*
- * This could happen in the AOT compiler case when the search hook is not
- * installed.
- */
- assembly = image->assembly;
- if (!assembly) {
- /* then we must load the assembly ourselve - see #60439 */
- assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
- if (!assembly)
- return NULL;
- }
- image = assembly->image;
- } else if (!image) {
- image = mono_defaults.corlib;
- }
-
- type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
- if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
- /* ignore the error and try again */
- mono_error_cleanup (error);
- mono_error_init (error);
- image = mono_defaults.corlib;
- type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
- }
-
- return type;
-}
-
-/**
- * mono_reflection_get_type_internal:
- *
- * Returns: may return NULL on success, sets error on failure.
- */
-static MonoType*
-mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
-{
- MonoClass *klass;
- GList *mod;
- int modval;
- gboolean bounded = FALSE;
-
- mono_error_init (error);
- if (!image)
- image = mono_defaults.corlib;
-
- if (!rootimage)
- rootimage = mono_defaults.corlib;
-
- if (ignorecase)
- klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
- else
- klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
-
- if (!klass)
- return NULL;
-
- for (mod = info->nested; mod; mod = mod->next) {
- gpointer iter = NULL;
- MonoClass *parent;
-
- parent = klass;
- mono_class_init (parent);
-
- while ((klass = mono_class_get_nested_types (parent, &iter))) {
- char *lastp;
- char *nested_name, *nested_nspace;
- gboolean match = TRUE;
-
- lastp = strrchr ((const char *)mod->data, '.');
- if (lastp) {
- /* Nested classes can have namespaces */
- int nspace_len;
-
- nested_name = g_strdup (lastp + 1);
- nspace_len = lastp - (char*)mod->data;
- nested_nspace = (char *)g_malloc (nspace_len + 1);
- memcpy (nested_nspace, mod->data, nspace_len);
- nested_nspace [nspace_len] = '\0';
-
- } else {
- nested_name = (char *)mod->data;
- nested_nspace = NULL;
- }
-
- if (nested_nspace) {
- if (ignorecase) {
- if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
- match = FALSE;
- } else {
- if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
- match = FALSE;
- }
- }
- if (match) {
- if (ignorecase) {
- if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
- match = FALSE;
- } else {
- if (strcmp (klass->name, nested_name) != 0)
- match = FALSE;
- }
- }
- if (lastp) {
- g_free (nested_name);
- g_free (nested_nspace);
- }
- if (match)
- break;
- }
-
- if (!klass)
- break;
- }
- if (!klass)
- return NULL;
-
- if (info->type_arguments) {
- MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
- MonoReflectionType *the_type;
- MonoType *instance;
- int i;
-
- for (i = 0; i < info->type_arguments->len; i++) {
- MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
-
- type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
- if (!type_args [i]) {
- g_free (type_args);
- return NULL;
- }
- }
-
- the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
- if (!the_type)
- return NULL;
-
- instance = mono_reflection_bind_generic_parameters (
- the_type, info->type_arguments->len, type_args, error);
-
- g_free (type_args);
- if (!instance)
- return NULL;
-
- klass = mono_class_from_mono_type (instance);
- }
-
- for (mod = info->modifiers; mod; mod = mod->next) {
- modval = GPOINTER_TO_UINT (mod->data);
- if (!modval) { /* byref: must be last modifier */
- return &klass->this_arg;
- } else if (modval == -1) {
- klass = mono_ptr_class_get (&klass->byval_arg);
- } else if (modval == -2) {
- bounded = TRUE;
- } else { /* array rank */
- klass = mono_bounded_array_class_get (klass, modval, bounded);
- }
- }
-
- return &klass->byval_arg;
-}
-
-/*
- * mono_reflection_get_type:
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- * @type_resolve: whenever type resolve was already tried
- *
- * Build a MonoType from the type description in @info.
- *
- */
-
-MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
- MonoError error;
- MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_type_checked:
- * @rootimage: the image of the currently active managed caller
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- * @type_resolve: whenever type resolve was already tried
- * @error: set on error.
- *
- * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
- *
- */
-MonoType*
-mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
- mono_error_init (error);
- return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
-}
-
-
-static MonoType*
-mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
-{
- MonoReflectionAssemblyBuilder *abuilder;
- MonoType *type;
- int i;
-
- mono_error_init (error);
- g_assert (assembly_is_dynamic (assembly));
- abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
- if (!abuilder)
- return NULL;
-
- /* Enumerate all modules */
-
- type = NULL;
- if (abuilder->modules) {
- for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
- MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
- type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
- if (type)
- break;
- if (!mono_error_ok (error))
- return NULL;
- }
- }
-
- if (!type && abuilder->loaded_modules) {
- for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
- MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
- type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
- if (type)
- break;
- if (!mono_error_ok (error))
- return NULL;
- }
- }
-
- return type;
-}
-
-MonoType*
-mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
-{
- MonoType *type;
- MonoReflectionAssembly *assembly;
- GString *fullName;
- GList *mod;
-
- mono_error_init (error);
-
- if (image && image_is_dynamic (image))
- type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
- else {
- type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
- }
- return_val_if_nok (error, NULL);
-
- if (type)
- return type;
- if (!mono_domain_has_type_resolve (mono_domain_get ()))
- return NULL;
-
- if (type_resolve) {
- if (*type_resolve)
- return NULL;
- else
- *type_resolve = TRUE;
- }
-
- /* Reconstruct the type name */
- fullName = g_string_new ("");
- if (info->name_space && (info->name_space [0] != '\0'))
- g_string_printf (fullName, "%s.%s", info->name_space, info->name);
- else
- g_string_printf (fullName, "%s", info->name);
- for (mod = info->nested; mod; mod = mod->next)
- g_string_append_printf (fullName, "+%s", (char*)mod->data);
-
- assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
- if (!is_ok (error)) {
- g_string_free (fullName, TRUE);
- return NULL;
- }
-
- if (assembly) {
- if (assembly_is_dynamic (assembly->assembly))
- type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
- info, ignorecase, error);
- else
- type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
- info, ignorecase, error);
- }
- g_string_free (fullName, TRUE);
- return_val_if_nok (error, NULL);
- return type;
-}
-
-void
-mono_reflection_free_type_info (MonoTypeNameParse *info)
-{
- g_list_free (info->modifiers);
- g_list_free (info->nested);
-
- if (info->type_arguments) {
- int i;
-
- for (i = 0; i < info->type_arguments->len; i++) {
- MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
-
- mono_reflection_free_type_info (subinfo);
- /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
- g_free (subinfo);
- }
-
- g_ptr_array_free (info->type_arguments, TRUE);
- }
-}
-
-/*
- * mono_reflection_type_from_name:
- * @name: type name.
- * @image: a metadata context (can be NULL).
- *
- * Retrieves a MonoType from its @name. If the name is not fully qualified,
- * it defaults to get the type from @image or, if @image is NULL or loading
- * from it fails, uses corlib.
- *
- */
-MonoType*
-mono_reflection_type_from_name (char *name, MonoImage *image)
-{
- MonoError error;
- MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_type_from_name_checked:
- * @name: type name.
- * @image: a metadata context (can be NULL).
- * @error: set on errror.
- *
- * Retrieves a MonoType from its @name. If the name is not fully qualified,
- * it defaults to get the type from @image or, if @image is NULL or loading
- * from it fails, uses corlib. On failure returns NULL and sets @error.
- *
- */
-MonoType*
-mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
-{
- MonoType *type = NULL;
- MonoTypeNameParse info;
- char *tmp;
-
- mono_error_init (error);
- /* Make a copy since parse_type modifies its argument */
- tmp = g_strdup (name);
-
- /*g_print ("requested type %s\n", str);*/
- if (mono_reflection_parse_type (tmp, &info)) {
- type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
- if (!is_ok (error)) {
- g_free (tmp);
- mono_reflection_free_type_info (&info);
- return NULL;
- }
- }
-
- g_free (tmp);
- mono_reflection_free_type_info (&info);
- return type;
-}
-
-/*
- * mono_reflection_get_token:
- *
- * Return the metadata token of OBJ which should be an object
- * representing a metadata element.
- */
-guint32
-mono_reflection_get_token (MonoObject *obj)
-{
- MonoError error;
- guint32 result = mono_reflection_get_token_checked (obj, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_token_checked:
- * @obj: the object
- * @error: set on error
- *
- * Return the metadata token of @obj which should be an object
- * representing a metadata element. On failure sets @error.
- */
-guint32
-mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
-
- if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
-
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
-
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- } else if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
-
- token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
- } else if (strcmp (klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
- } else if (strcmp (klass->name, "RuntimeType") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, 0);
- MonoClass *mc = mono_class_from_mono_type (type);
- if (!mono_class_init (mc)) {
- mono_error_set_for_class_failure (error, mc);
- return 0;
- }
-
- token = mc->type_token;
- } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
- strcmp (klass->name, "MonoMethod") == 0 ||
- strcmp (klass->name, "MonoGenericMethod") == 0 ||
- strcmp (klass->name, "MonoGenericCMethod") == 0) {
- MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
- if (m->method->is_inflated) {
- MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
- return inflated->declaring->token;
- } else {
- token = m->method->token;
- }
- } else if (strcmp (klass->name, "MonoField") == 0) {
- MonoReflectionField *f = (MonoReflectionField*)obj;
-
- if (is_field_on_inst (f->field)) {
- MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
-
- if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
- int field_index = f->field - dgclass->fields;
- MonoObject *obj;
-
- g_assert (field_index >= 0 && field_index < dgclass->count_fields);
- obj = dgclass->field_objects [field_index];
- return mono_reflection_get_token_checked (obj, error);
- }
- }
- token = mono_class_get_field_token (f->field);
- } else if (strcmp (klass->name, "MonoProperty") == 0) {
- MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
-
- token = mono_class_get_property_token (p->property);
- } else if (strcmp (klass->name, "MonoEvent") == 0) {
- MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
-
- token = mono_class_get_event_token (p->event);
- } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
- MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
- MonoClass *member_class = mono_object_class (p->MemberImpl);
- g_assert (mono_class_is_reflection_method_or_constructor (member_class));
-
- token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
- } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
- MonoReflectionModule *m = (MonoReflectionModule*)obj;
-
- token = m->token;
- } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
- token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
- } else {
- mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
- klass->name_space, klass->name);
- return 0;
- }
-
- return token;
-}
-
-/*
- * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
- * The @is_enum flag only affects the error message that's displayed on failure.
- */
-static MonoType*
-cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
-{
- MonoError inner_error;
- MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
- if (!t) {
- mono_error_set_type_load_name (error, g_strdup(n), NULL,
- "Could not load %s %s while decoding custom attribute: %s",
- is_enum ? "enum type": "type",
- n,
- mono_error_get_message (&inner_error));
- mono_error_cleanup (&inner_error);
- return NULL;
- }
- return t;
-}
-
-static MonoClass*
-load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
-{
- char *n;
- MonoType *t;
- int slen = mono_metadata_decode_value (p, &p);
-
- mono_error_init (error);
-
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, TRUE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- p += slen;
- *end = p;
- return mono_class_from_mono_type (t);
-}
-
-static void*
-load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
-{
- int slen, type = t->type;
- MonoClass *tklass = t->data.klass;
-
- mono_error_init (error);
-
-handle_enum:
- switch (type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN: {
- MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
- *bval = *p;
- *end = p + 1;
- return bval;
- }
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2: {
- guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
- *val = read16 (p);
- *end = p + 2;
- return val;
- }
-#if SIZEOF_VOID_P == 4
- case MONO_TYPE_U:
- case MONO_TYPE_I:
-#endif
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4: {
- guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
- *val = read32 (p);
- *end = p + 4;
- return val;
- }
-#if SIZEOF_VOID_P == 8
- case MONO_TYPE_U: /* error out instead? this should probably not happen */
- case MONO_TYPE_I:
-#endif
- case MONO_TYPE_U8:
- case MONO_TYPE_I8: {
- guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
- *val = read64 (p);
- *end = p + 8;
- return val;
- }
- case MONO_TYPE_R8: {
- double *val = (double *)g_malloc (sizeof (double));
- readr8 (p, val);
- *end = p + 8;
- return val;
- }
- case MONO_TYPE_VALUETYPE:
- if (t->data.klass->enumtype) {
- type = mono_class_enum_basetype (t->data.klass)->type;
- goto handle_enum;
- } else {
- MonoClass *k = t->data.klass;
-
- if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
- guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
- *val = read64 (p);
- *end = p + 8;
- return val;
- }
- }
- g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
- break;
-
- case MONO_TYPE_STRING:
- if (*p == (char)0xFF) {
- *end = p + 1;
- return NULL;
- }
- slen = mono_metadata_decode_value (p, &p);
- *end = p + slen;
- return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
- case MONO_TYPE_CLASS: {
- MonoReflectionType *rt;
- char *n;
- MonoType *t;
- if (*p == (char)0xFF) {
- *end = p + 1;
- return NULL;
- }
-handle_type:
- slen = mono_metadata_decode_value (p, &p);
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, FALSE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- *end = p + slen;
-
- rt = mono_type_get_object_checked (mono_domain_get (), t, error);
- if (!mono_error_ok (error))
- return NULL;
-
- return rt;
- }
- case MONO_TYPE_OBJECT: {
- char subt = *p++;
- MonoObject *obj;
- MonoClass *subc = NULL;
- void *val;
-
- if (subt == 0x50) {
- goto handle_type;
- } else if (subt == 0x0E) {
- type = MONO_TYPE_STRING;
- goto handle_enum;
- } else if (subt == 0x1D) {
- MonoType simple_type = {{0}};
- int etype = *p;
- p ++;
-
- type = MONO_TYPE_SZARRAY;
- if (etype == 0x50) {
- tklass = mono_defaults.systemtype_class;
- } else if (etype == 0x55) {
- tklass = load_cattr_enum_type (image, p, &p, error);
- if (!mono_error_ok (error))
- return NULL;
- } else {
- if (etype == 0x51)
- /* See Partition II, Appendix B3 */
- etype = MONO_TYPE_OBJECT;
- simple_type.type = (MonoTypeEnum)etype;
- tklass = mono_class_from_mono_type (&simple_type);
- }
- goto handle_enum;
- } else if (subt == 0x55) {
- char *n;
- MonoType *t;
- slen = mono_metadata_decode_value (p, &p);
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, FALSE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- p += slen;
- subc = mono_class_from_mono_type (t);
- } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
- MonoType simple_type = {{0}};
- simple_type.type = (MonoTypeEnum)subt;
- subc = mono_class_from_mono_type (&simple_type);
- } else {
- g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
- }
- val = load_cattr_value (image, &subc->byval_arg, p, end, error);
- obj = NULL;
- if (mono_error_ok (error)) {
- obj = mono_object_new_checked (mono_domain_get (), subc, error);
- g_assert (!subc->has_references);
- if (mono_error_ok (error))
- mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
- }
-
- g_free (val);
- return obj;
- }
- case MONO_TYPE_SZARRAY: {
- MonoArray *arr;
- guint32 i, alen, basetype;
- alen = read32 (p);
- p += 4;
- if (alen == 0xffffffff) {
- *end = p;
- return NULL;
- }
- arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
- return_val_if_nok (error, NULL);
- basetype = tklass->byval_arg.type;
- if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
- basetype = mono_class_enum_basetype (tklass)->type;
- switch (basetype)
- {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- for (i = 0; i < alen; i++) {
- MonoBoolean val = *p++;
- mono_array_set (arr, MonoBoolean, i, val);
- }
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- for (i = 0; i < alen; i++) {
- guint16 val = read16 (p);
- mono_array_set (arr, guint16, i, val);
- p += 2;
- }
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- for (i = 0; i < alen; i++) {
- guint32 val = read32 (p);
- mono_array_set (arr, guint32, i, val);
- p += 4;
- }
- break;
- case MONO_TYPE_R8:
- for (i = 0; i < alen; i++) {
- double val;
- readr8 (p, &val);
- mono_array_set (arr, double, i, val);
- p += 8;
- }
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- for (i = 0; i < alen; i++) {
- guint64 val = read64 (p);
- mono_array_set (arr, guint64, i, val);
- p += 8;
- }
- break;
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_SZARRAY:
- for (i = 0; i < alen; i++) {
- MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
- if (!mono_error_ok (error))
- return NULL;
- mono_array_setref (arr, i, item);
- }
- break;
- default:
- g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
- }
- *end=p;
- return arr;
- }
- default:
- g_error ("Type 0x%02x not handled in custom attr value decoding", type);
- }
- return NULL;
-}
-
-static MonoObject*
-load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
-{
- mono_error_init (error);
-
- gboolean is_ref = type_is_reference (t);
-
- void *val = load_cattr_value (image, t, p, end, error);
- if (!is_ok (error)) {
- if (is_ref)
- g_free (val);
- return NULL;
- }
-
- if (is_ref)
- return (MonoObject*)val;
-
- MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
- g_free (val);
- return boxed;
-}
-
-static MonoObject*
-create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
-{
- static MonoMethod *ctor;
- MonoObject *retval;
- void *params [2], *unboxed;
-
- mono_error_init (error);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
-
- params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
- return_val_if_nok (error, NULL);
-
- params [1] = val;
- retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
- return_val_if_nok (error, NULL);
- unboxed = mono_object_unbox (retval);
-
- mono_runtime_invoke_checked (ctor, unboxed, params, error);
- return_val_if_nok (error, NULL);
-
- return retval;
-}
-
-static MonoObject*
-create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
-{
- static MonoMethod *ctor;
- MonoObject *retval;
- void *unboxed, *params [2];
-
- mono_error_init (error);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
-
- params [0] = minfo;
- params [1] = typedarg;
- retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
- return_val_if_nok (error, NULL);
-
- unboxed = mono_object_unbox (retval);
-
- mono_runtime_invoke_checked (ctor, unboxed, params, error);
- return_val_if_nok (error, NULL);
-
- return retval;
-}
-
-static gboolean
-type_is_reference (MonoType *type)
-{
- switch (type->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- case MONO_TYPE_R4:
- case MONO_TYPE_VALUETYPE:
- return FALSE;
- default:
- return TRUE;
- }
-}
-
-static void
-free_param_data (MonoMethodSignature *sig, void **params) {
- int i;
- for (i = 0; i < sig->param_count; ++i) {
- if (!type_is_reference (sig->params [i]))
- g_free (params [i]);
- }
-}
-
-/*
- * Find the field index in the metadata FieldDef table.
- */
-static guint32
-find_field_index (MonoClass *klass, MonoClassField *field) {
- int i;
-
- for (i = 0; i < klass->field.count; ++i) {
- if (field == &klass->fields [i])
- return klass->field.first + 1 + i;
- }
- return 0;
-}
-
-/*
- * Find the property index in the metadata Property table.
- */
-static guint32
-find_property_index (MonoClass *klass, MonoProperty *property) {
- int i;
-
- for (i = 0; i < klass->ext->property.count; ++i) {
- if (property == &klass->ext->properties [i])
- return klass->ext->property.first + 1 + i;
- }
- return 0;
-}
-
-/*
- * Find the event index in the metadata Event table.
- */
-static guint32
-find_event_index (MonoClass *klass, MonoEvent *event) {
- int i;
-
- for (i = 0; i < klass->ext->event.count; ++i) {
- if (event == &klass->ext->events [i])
- return klass->ext->event.first + 1 + i;
- }
- return 0;
-}
-
-static MonoObject*
-create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
-{
- const char *p = (const char*)data;
- const char *named;
- guint32 i, j, num_named;
- MonoObject *attr;
- void *params_buf [32];
- void **params = NULL;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- mono_class_init (method->klass);
-
- if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- return NULL;
- }
-
- if (len == 0) {
- attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
- if (!mono_error_ok (error)) return NULL;
-
- mono_runtime_invoke_checked (method, attr, NULL, error);
- if (!mono_error_ok (error))
- return NULL;
-
- return attr;
- }
-
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return NULL;
-
- /*g_print ("got attr %s\n", method->klass->name);*/
-
- sig = mono_method_signature (method);
- if (sig->param_count < 32) {
- params = params_buf;
- memset (params, 0, sizeof (void*) * sig->param_count);
- } else {
- /* Allocate using GC so it gets GC tracking */
- params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
- }
-
- /* skip prolog */
- p += 2;
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
- if (!mono_error_ok (error))
- goto fail;
- }
-
- named = p;
- attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
- if (!mono_error_ok (error)) goto fail;
-
- MonoObject *exc = NULL;
- mono_runtime_try_invoke (method, attr, params, &exc, error);
- if (!mono_error_ok (error))
- goto fail;
- if (exc) {
- mono_error_set_exception_instance (error, (MonoException*)exc);
- goto fail;
- }
-
- num_named = read16 (named);
- named += 2;
- for (j = 0; j < num_named; j++) {
- gint name_len;
- char *name, named_type, data_type;
- named_type = *named++;
- data_type = *named++; /* type of data */
- if (data_type == MONO_TYPE_SZARRAY)
- data_type = *named++;
- if (data_type == MONO_TYPE_ENUM) {
- gint type_len;
- char *type_name;
- type_len = mono_metadata_decode_blob_size (named, &named);
- type_name = (char *)g_malloc (type_len + 1);
- memcpy (type_name, named, type_len);
- type_name [type_len] = 0;
- named += type_len;
- /* FIXME: lookup the type and check type consistency */
- g_free (type_name);
- }
- name_len = mono_metadata_decode_blob_size (named, &named);
- name = (char *)g_malloc (name_len + 1);
- memcpy (name, named, name_len);
- name [name_len] = 0;
- named += name_len;
- if (named_type == 0x53) {
- MonoClassField *field;
- void *val;
-
- /* how this fail is a blackbox */
- field = mono_class_get_field_from_name (mono_object_class (attr), name);
- if (!field) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
- g_free (name);
- goto fail;
- }
-
- val = load_cattr_value (image, field->type, named, &named, error);
- if (!mono_error_ok (error)) {
- g_free (name);
- if (!type_is_reference (field->type))
- g_free (val);
- goto fail;
- }
-
- mono_field_set_value (attr, field, val);
- if (!type_is_reference (field->type))
- g_free (val);
- } else if (named_type == 0x54) {
- MonoProperty *prop;
- void *pparams [1];
- MonoType *prop_type;
-
- prop = mono_class_get_property_from_name (mono_object_class (attr), name);
-
- if (!prop) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
- g_free (name);
- goto fail;
- }
-
- if (!prop->set) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
- g_free (name);
- goto fail;
- }
-
- /* can we have more that 1 arg in a custom attr named property? */
- prop_type = prop->get? mono_method_signature (prop->get)->ret :
- mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
-
- pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
- if (!mono_error_ok (error)) {
- g_free (name);
- if (!type_is_reference (prop_type))
- g_free (pparams [0]);
- goto fail;
- }
-
-
- mono_property_set_value_checked (prop, attr, pparams, error);
- if (!type_is_reference (prop_type))
- g_free (pparams [0]);
- if (!is_ok (error)) {
- g_free (name);
- goto fail;
- }
- }
- g_free (name);
- }
-
- free_param_data (method->signature, params);
- if (params != params_buf)
- mono_gc_free_fixed (params);
-
- return attr;
-
-fail:
- free_param_data (method->signature, params);
- if (params != params_buf)
- mono_gc_free_fixed (params);
- return NULL;
-}
-
-/*
- * mono_reflection_create_custom_attr_data_args:
- *
- * Create an array of typed and named arguments from the cattr blob given by DATA.
- * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
- * NAMED_ARG_INFO will contain information about the named arguments.
- */
-void
-mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
-{
- MonoArray *typedargs, *namedargs;
- MonoClass *attrklass;
- MonoDomain *domain;
- const char *p = (const char*)data;
- const char *named;
- guint32 i, j, num_named;
- CattrNamedArg *arginfo = NULL;
-
- *typed_args = NULL;
- *named_args = NULL;
- *named_arg_info = NULL;
-
- mono_error_init (error);
-
- if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- return;
- }
-
- mono_class_init (method->klass);
-
- domain = mono_domain_get ();
-
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return;
-
- typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
- return_if_nok (error);
-
- /* skip prolog */
- p += 2;
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- MonoObject *obj;
-
- obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
- return_if_nok (error);
- mono_array_setref (typedargs, i, obj);
- }
-
- named = p;
- num_named = read16 (named);
- namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
- return_if_nok (error);
- named += 2;
- attrklass = method->klass;
-
- arginfo = g_new0 (CattrNamedArg, num_named);
- *named_arg_info = arginfo;
-
- for (j = 0; j < num_named; j++) {
- gint name_len;
- char *name, named_type, data_type;
- named_type = *named++;
- data_type = *named++; /* type of data */
- if (data_type == MONO_TYPE_SZARRAY)
- data_type = *named++;
- if (data_type == MONO_TYPE_ENUM) {
- gint type_len;
- char *type_name;
- type_len = mono_metadata_decode_blob_size (named, &named);
- if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
- goto fail;
-
- type_name = (char *)g_malloc (type_len + 1);
- memcpy (type_name, named, type_len);
- type_name [type_len] = 0;
- named += type_len;
- /* FIXME: lookup the type and check type consistency */
- g_free (type_name);
- }
- name_len = mono_metadata_decode_blob_size (named, &named);
- if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
- goto fail;
- name = (char *)g_malloc (name_len + 1);
- memcpy (name, named, name_len);
- name [name_len] = 0;
- named += name_len;
- if (named_type == 0x53) {
- MonoObject *obj;
- MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
-
- if (!field) {
- g_free (name);
- goto fail;
- }
-
- arginfo [j].type = field->type;
- arginfo [j].field = field;
-
- obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
- if (!is_ok (error)) {
- g_free (name);
- return;
- }
- mono_array_setref (namedargs, j, obj);
-
- } else if (named_type == 0x54) {
- MonoObject *obj;
- MonoType *prop_type;
- MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
-
- if (!prop || !prop->set) {
- g_free (name);
- goto fail;
- }
-
- prop_type = prop->get? mono_method_signature (prop->get)->ret :
- mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
-
- arginfo [j].type = prop_type;
- arginfo [j].prop = prop;
-
- obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
- if (!is_ok (error)) {
- g_free (name);
- return;
- }
- mono_array_setref (namedargs, j, obj);
- }
- g_free (name);
- }
-
- *typed_args = typedargs;
- *named_args = namedargs;
- return;
-fail:
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- g_free (arginfo);
- *named_arg_info = NULL;
-}
-
-static gboolean
-reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
-{
- MonoDomain *domain;
- MonoArray *typedargs, *namedargs;
- MonoImage *image;
- MonoMethod *method;
- CattrNamedArg *arginfo = NULL;
- int i;
-
- mono_error_init (error);
-
- *ctor_args = NULL;
- *named_args = NULL;
-
- if (len == 0)
- return TRUE;
-
- image = assembly->assembly->image;
- method = ref_method->method;
- domain = mono_object_domain (ref_method);
-
- if (!mono_class_init (method->klass)) {
- mono_error_set_for_class_failure (error, method->klass);
- goto leave;
- }
-
- mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
- if (!is_ok (error))
- goto leave;
-
- if (!typedargs || !namedargs)
- goto leave;
-
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
- MonoObject *typedarg;
-
- typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
- if (!is_ok (error))
- goto leave;
- mono_array_setref (typedargs, i, typedarg);
- }
-
- for (i = 0; i < mono_array_length (namedargs); ++i) {
- MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
- MonoObject *typedarg, *namedarg, *minfo;
-
- if (arginfo [i].prop) {
- minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
- if (!minfo)
- goto leave;
- } else {
- minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
- if (!is_ok (error))
- goto leave;
- }
-
- typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
- if (!is_ok (error))
- goto leave;
- namedarg = create_cattr_named_arg (minfo, typedarg, error);
- if (!is_ok (error))
- goto leave;
-
- mono_array_setref (namedargs, i, namedarg);
- }
-
- *ctor_args = typedargs;
- *named_args = namedargs;
-
-leave:
- g_free (arginfo);
- return mono_error_ok (error);
-}
-
-void
-ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
-{
- MonoError error;
- (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static MonoObject*
-create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
-{
- static MonoMethod *ctor;
-
- MonoDomain *domain;
- MonoObject *attr;
- void *params [4];
-
- mono_error_init (error);
-
- g_assert (image->assembly);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
-
- domain = mono_domain_get ();
- attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
- return_val_if_nok (error, NULL);
- params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
- return_val_if_nok (error, NULL);
- params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
- return_val_if_nok (error, NULL);
- params [2] = (gpointer)&cattr->data;
- params [3] = &cattr->data_size;
-
- mono_runtime_invoke_checked (ctor, attr, params, error);
- return_val_if_nok (error, NULL);
- return attr;
-}
-
-static MonoArray*
-mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
-{
- MonoArray *result;
- MonoObject *attr;
- int i, n;
-
- mono_error_init (error);
-
- for (i = 0; i < cinfo->num_attrs; ++i) {
- MonoCustomAttrEntry *centry = &cinfo->attrs[i];
- if (!centry->ctor) {
- /* The cattr type is not finished yet */
- /* We should include the type name but cinfo doesn't contain it */
- mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
- return NULL;
- }
- }
-
- n = 0;
- if (attr_klass) {
- for (i = 0; i < cinfo->num_attrs; ++i) {
- MonoMethod *ctor = cinfo->attrs[i].ctor;
- g_assert (ctor);
- if (mono_class_is_assignable_from (attr_klass, ctor->klass))
- n++;
- }
- } else {
- n = cinfo->num_attrs;
- }
-
- result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
- return_val_if_nok (error, NULL);
- n = 0;
- for (i = 0; i < cinfo->num_attrs; ++i) {
- MonoCustomAttrEntry *centry = &cinfo->attrs [i];
- if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
- attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
- if (!mono_error_ok (error))
- return result;
- mono_array_setref (result, n, attr);
- n ++;
- }
- }
- return result;
-}
-
-MonoArray*
-mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
-{
- MonoError error;
- MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
- mono_error_assert_ok (&error); /*FIXME proper error handling*/
-
- return result;
-}
-
-static MonoArray*
-mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
-{
- MonoArray *result;
- MonoObject *attr;
- int i;
-
- mono_error_init (error);
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
- return_val_if_nok (error, NULL);
- for (i = 0; i < cinfo->num_attrs; ++i) {
- attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
- return_val_if_nok (error, NULL);
- mono_array_setref (result, i, attr);
- }
- return result;
-}
-
-/**
- * mono_custom_attrs_from_index:
- *
- * Returns: NULL if no attributes are found or if a loading error occurs.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
- mono_error_cleanup (&error);
- return result;
-}
-/**
- * mono_custom_attrs_from_index_checked:
- *
- * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
-{
- guint32 mtoken, i, len;
- guint32 cols [MONO_CUSTOM_ATTR_SIZE];
- MonoTableInfo *ca;
- MonoCustomAttrInfo *ainfo;
- GList *tmp, *list = NULL;
- const char *data;
- MonoCustomAttrEntry* attr;
-
- mono_error_init (error);
-
- ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-
- i = mono_metadata_custom_attrs_from_index (image, idx);
- if (!i)
- return NULL;
- i --;
- while (i < ca->rows) {
- if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
- break;
- list = g_list_prepend (list, GUINT_TO_POINTER (i));
- ++i;
- }
- len = g_list_length (list);
- if (!len)
- return NULL;
- ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
- ainfo->num_attrs = len;
- ainfo->image = image;
- for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
- mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
- mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
- switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
- case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
- mtoken |= MONO_TOKEN_METHOD_DEF;
- break;
- case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
- mtoken |= MONO_TOKEN_MEMBER_REF;
- break;
- default:
- g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
- break;
- }
- attr = &ainfo->attrs [i - 1];
- attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
- if (!attr->ctor) {
- g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
- g_list_free (list);
- g_free (ainfo);
- return NULL;
- }
-
- if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
- /*FIXME raising an exception here doesn't make any sense*/
- g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
- g_list_free (list);
- g_free (ainfo);
- return NULL;
- }
- data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
- attr->data_size = mono_metadata_decode_value (data, &data);
- attr->data = (guchar*)data;
- }
- g_list_free (list);
-
- return ainfo;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_method (MonoMethod *method)
-{
- MonoError error;
- MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
- mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- /*
- * An instantiated method has the same cattrs as the generic method definition.
- *
- * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
- * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
- */
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
- return lookup_custom_attr (method->klass->image, method);
-
- if (!method->token)
- /* Synthetic methods */
- return NULL;
-
- idx = mono_method_get_index (method);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_METHODDEF;
- return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_class (MonoClass *klass)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
-
- if (image_is_dynamic (klass->image))
- return lookup_custom_attr (klass->image, klass);
-
- if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
- idx = mono_metadata_token_index (klass->sizes.generic_param_token);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_GENERICPAR;
- } else {
- idx = mono_metadata_token_index (klass->type_token);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_TYPEDEF;
- }
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly (MonoAssembly *assembly)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- if (image_is_dynamic (assembly->image))
- return lookup_custom_attr (assembly->image, assembly);
- idx = 1; /* there is only one assembly */
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
- return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
-}
-
-static MonoCustomAttrInfo*
-mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (image))
- return lookup_custom_attr (image, image);
- idx = 1; /* there is only one module */
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_MODULE;
- return mono_custom_attrs_from_index_checked (image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (klass->image)) {
- property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
- return lookup_custom_attr (klass->image, property);
- }
- idx = find_property_index (klass, property);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_PROPERTY;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (klass->image)) {
- event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
- return lookup_custom_attr (klass->image, event);
- }
- idx = find_event_index (klass, event);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_EVENT;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
-{
- guint32 idx;
- mono_error_init (error);
-
- if (image_is_dynamic (klass->image)) {
- field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
- return lookup_custom_attr (klass->image, field);
- }
- idx = find_field_index (klass, field);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_FIELDDEF;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-/**
- * mono_custom_attrs_from_param:
- * @method: handle to the method that we want to retrieve custom parameter information from
- * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
- *
- * The result must be released with mono_custom_attrs_free().
- *
- * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_custom_attrs_from_param_checked:
- * @method: handle to the method that we want to retrieve custom parameter information from
- * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
- * @error: set on error
- *
- * The result must be released with mono_custom_attrs_free().
- *
- * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
-{
- MonoTableInfo *ca;
- guint32 i, idx, method_index;
- guint32 param_list, param_last, param_pos, found;
- MonoImage *image;
- MonoReflectionMethodAux *aux;
-
- mono_error_init (error);
-
- /*
- * An instantiated method has the same cattrs as the generic method definition.
- *
- * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
- * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
- */
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- if (image_is_dynamic (method->klass->image)) {
- MonoCustomAttrInfo *res, *ainfo;
- int size;
-
- aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
- if (!aux || !aux->param_cattr)
- return NULL;
-
- /* Need to copy since it will be freed later */
- ainfo = aux->param_cattr [param];
- if (!ainfo)
- return NULL;
- size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
- res = (MonoCustomAttrInfo *)g_malloc0 (size);
- memcpy (res, ainfo, size);
- return res;
- }
-
- image = method->klass->image;
- method_index = mono_method_get_index (method);
- if (!method_index)
- return NULL;
- ca = &image->tables [MONO_TABLE_METHOD];
-
- param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
- if (method_index == ca->rows) {
- ca = &image->tables [MONO_TABLE_PARAM];
- param_last = ca->rows + 1;
- } else {
- param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
- ca = &image->tables [MONO_TABLE_PARAM];
- }
- found = FALSE;
- for (i = param_list; i < param_last; ++i) {
- param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
- if (param_pos == param) {
- found = TRUE;
- break;
- }
- }
- if (!found)
- return NULL;
- idx = i;
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_PARAMDEF;
- return mono_custom_attrs_from_index_checked (image, idx, error);
-}
-
-gboolean
-mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
-{
- int i;
- for (i = 0; i < ainfo->num_attrs; ++i) {
- MonoClass *klass = ainfo->attrs [i].ctor->klass;
- if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
- return TRUE;
- }
- return FALSE;
-}
-
-MonoObject*
-mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
-{
- MonoError error;
- MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
- mono_error_assert_ok (&error); /*FIXME proper error handling*/
- return res;
-}
-
-MonoObject*
-mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
-{
- int i, attr_index;
- MonoArray *attrs;
-
- mono_error_init (error);
-
- attr_index = -1;
- for (i = 0; i < ainfo->num_attrs; ++i) {
- MonoClass *klass = ainfo->attrs [i].ctor->klass;
- if (mono_class_has_parent (klass, attr_klass)) {
- attr_index = i;
- break;
- }
- }
- if (attr_index == -1)
- return NULL;
-
- attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
- if (!mono_error_ok (error))
- return NULL;
- return mono_array_get (attrs, MonoObject*, attr_index);
-}
-
-/*
- * mono_reflection_get_custom_attrs_info:
- * @obj: a reflection object handle
- *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
- *
- * FIXME this function leaks like a sieve for SRE objects.
- */
-MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info (MonoObject *obj)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_custom_attrs_info_checked:
- * @obj: a reflection object handle
- * @error: set on error
- *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
- *
- * On failure returns NULL and sets @error.
- *
- * FIXME this function leaks like a sieve for SRE objects.
- */
-MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
-{
- MonoClass *klass;
- MonoCustomAttrInfo *cinfo = NULL;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
- if (klass == mono_defaults.runtimetype_class) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (type);
- /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
- cinfo = mono_custom_attrs_from_class_checked (klass, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
- MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
- cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
- MonoReflectionModule *module = (MonoReflectionModule*)obj;
- cinfo = mono_custom_attrs_from_module (module->image, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoProperty", klass->name) == 0) {
- MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
- cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoEvent", klass->name) == 0) {
- MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
- cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoField", klass->name) == 0) {
- MonoReflectionField *rfield = (MonoReflectionField*)obj;
- cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
- return_val_if_nok (error, NULL);
- } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
- cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
- return_val_if_nok (error, NULL);
- } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
- cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
- MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
- MonoClass *member_class = mono_object_class (param->MemberImpl);
- if (mono_class_is_reflection_method_or_constructor (member_class)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
- cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- } else if (is_sr_mono_property (member_class)) {
- MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
- MonoMethod *method;
- if (!(method = prop->property->get))
- method = prop->property->set;
- g_assert (method);
-
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- }
-#ifndef DISABLE_REFLECTION_EMIT
- else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
- MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
- return_val_if_nok (error, NULL);
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
- MonoMethod *method = NULL;
- if (is_sre_ctor_builder (mono_object_class (c->cb)))
- method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
- else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
- method = ((MonoReflectionMethod *)c->cb)->method;
- else
- g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
-
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- }
-#endif
- else {
- char *type_name = mono_type_get_full_name (member_class);
- mono_error_set_not_supported (error,
- "Custom attributes on a ParamInfo with member %s are not supported",
- type_name);
- g_free (type_name);
- return NULL;
- }
- } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
- MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
- } else if (strcmp ("TypeBuilder", klass->name) == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
- } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
- MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
- } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
- } else if (strcmp ("MethodBuilder", klass->name) == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
- } else if (strcmp ("FieldBuilder", klass->name) == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
- } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
- MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
- cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
- return_val_if_nok (error, NULL);
- } else { /* handle other types here... */
- g_error ("get custom attrs not yet supported for %s", klass->name);
- }
-
- return cinfo;
-}
-
-/*
- * mono_reflection_get_custom_attrs_by_type:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
- * of that type are returned. The objects are fully build. Return NULL if a loading error
- * occurs.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
-{
- MonoArray *result;
- MonoCustomAttrInfo *cinfo;
-
- mono_error_init (error);
-
- cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
- return_val_if_nok (error, NULL);
- if (cinfo) {
- result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- if (!result)
- return NULL;
- } else {
- result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
- }
-
- return result;
-}
-
-/*
- * mono_reflection_get_custom_attrs:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. The objects are fully build. Return NULL if a loading error
- * occurs.
- */
-MonoArray*
-mono_reflection_get_custom_attrs (MonoObject *obj)
-{
- MonoError error;
-
- return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
-}
-
-/*
- * mono_reflection_get_custom_attrs_data:
- * @obj: a reflection obj handle
- *
- * Returns an array of System.Reflection.CustomAttributeData,
- * which include information about attributes reflected on
- * types loaded using the Reflection Only methods
- */
-MonoArray*
-mono_reflection_get_custom_attrs_data (MonoObject *obj)
-{
- MonoError error;
- MonoArray* result;
- result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/*
- * mono_reflection_get_custom_attrs_data_checked:
- * @obj: a reflection obj handle
- * @error: set on error
- *
- * Returns an array of System.Reflection.CustomAttributeData,
- * which include information about attributes reflected on
- * types loaded using the Reflection Only methods
- */
-MonoArray*
-mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
-{
- MonoArray *result;
- MonoCustomAttrInfo *cinfo;
-
- mono_error_init (error);
-
- cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
- return_val_if_nok (error, NULL);
- if (cinfo) {
- result = mono_custom_attrs_data_construct (cinfo, error);
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- return_val_if_nok (error, NULL);
- } else
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
-
- return result;
-}
-
-static MonoReflectionType*
-mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
-{
- static MonoMethod *method_get_underlying_system_type = NULL;
- MonoReflectionType *rt;
- MonoMethod *usertype_method;
-
- mono_error_init (error);
-
- if (!method_get_underlying_system_type)
- method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
-
- usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
-
- rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
-
- return rt;
-}
-
-
-static gboolean
-is_corlib_type (MonoClass *klass)
-{
- return klass->image == mono_defaults.corlib;
-}
-
-#define check_corlib_type_cached(_class, _namespace, _name) do { \
- static MonoClass *cached_class; \
- if (cached_class) \
- return cached_class == _class; \
- if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
- cached_class = _class; \
- return TRUE; \
- } \
- return FALSE; \
-} while (0) \
-
-
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-is_sre_array (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
-}
-
-static gboolean
-is_sre_byref (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
-}
-
-static gboolean
-is_sre_pointer (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
-}
-
-static gboolean
-is_sre_generic_instance (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
-}
-
-static gboolean
-is_sre_type_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
-}
-
-static gboolean
-is_sre_method_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
-}
-
-static gboolean
-is_sre_ctor_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
-}
-
-static gboolean
-is_sre_field_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
-}
-
-static gboolean
-is_sre_method_on_tb_inst (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
-}
-
-static gboolean
-is_sre_ctor_on_tb_inst (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
-}
-
-MonoType*
-mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
-{
- MonoClass *klass;
- mono_error_init (error);
-
- if (!ref)
- return NULL;
- if (ref->type)
- return ref->type;
-
- if (is_usertype (ref)) {
- ref = mono_reflection_type_get_underlying_system_type (ref, error);
- if (ref == NULL || is_usertype (ref) || !is_ok (error))
- return NULL;
- if (ref->type)
- return ref->type;
- }
-
- klass = mono_object_class (ref);
-
- if (is_sre_array (klass)) {
- MonoType *res;
- MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- if (sre_array->rank == 0) //single dimentional array
- res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
- else
- res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
- sre_array->type.type = res;
- return res;
- } else if (is_sre_byref (klass)) {
- MonoType *res;
- MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- res = &mono_class_from_mono_type (base)->this_arg;
- sre_byref->type.type = res;
- return res;
- } else if (is_sre_pointer (klass)) {
- MonoType *res;
- MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- res = &mono_ptr_class_get (base)->byval_arg;
- sre_pointer->type.type = res;
- return res;
- } else if (is_sre_generic_instance (klass)) {
- MonoType *res, **types;
- MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
- int i, count;
-
- count = mono_array_length (gclass->type_arguments);
- types = g_new0 (MonoType*, count);
- for (i = 0; i < count; ++i) {
- MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
- types [i] = mono_reflection_type_get_handle (t, error);
- if (!types[i] || !is_ok (error)) {
- g_free (types);
- return NULL;
- }
- }
-
- res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
- g_free (types);
- g_assert (res);
- gclass->type.type = res;
- return res;
- }
-
- g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
- return NULL;
-}
-
-void
-ves_icall_SymbolType_create_unmanaged_type (MonoReflectionType *type)
-{
- MonoError error;
- mono_reflection_type_get_handle (type, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static gboolean
-reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
-{
- MonoDomain *domain = mono_object_domain ((MonoObject*)type);
- MonoClass *klass;
-
- mono_error_init (error);
-
- MonoType *res = mono_reflection_type_get_handle (type, error);
-
- if (!res && is_ok (error)) {
- mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
- }
- return_val_if_nok (error, FALSE);
-
- klass = mono_class_from_mono_type (res);
-
- mono_loader_lock (); /*same locking as mono_type_get_object_checked */
- mono_domain_lock (domain);
-
- if (!image_is_dynamic (klass->image)) {
- mono_class_setup_supertypes (klass);
- } else {
- if (!domain->type_hash)
- domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
- (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
- mono_g_hash_table_insert (domain->type_hash, res, type);
- }
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-
- return TRUE;
-}
-
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
-{
- MonoError error;
- (void) reflection_register_with_runtime (type, &error);
- mono_error_set_pending_exception (&error);
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
- MonoMethodSignature *sig;
- int count, i;
-
- mono_error_init (error);
-
- count = parameters? mono_array_length (parameters): 0;
-
- sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
- sig->param_count = count;
- sig->sentinelpos = -1; /* FIXME */
- for (i = 0; i < count; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
- }
- return sig;
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (image, ctor->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- sig->ret = &mono_defaults.void_class->byval_arg;
- return sig;
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (image, method->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- if (method->rtype) {
- sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
- } else {
- sig->ret = &mono_defaults.void_class->byval_arg;
- }
- sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
- return sig;
-}
-
-static MonoMethodSignature*
-dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (NULL, method->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- if (method->rtype) {
- sig->ret = mono_reflection_type_get_handle (method->rtype, error);
- if (!is_ok (error)) {
- g_free (sig);
- return NULL;
- }
- } else {
- sig->ret = &mono_defaults.void_class->byval_arg;
- }
- sig->generic_param_count = 0;
- return sig;
-}
-
-static void
-get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (prop);
- if (strcmp (klass->name, "PropertyBuilder") == 0) {
- MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
- *name = mono_string_to_utf8_checked (pb->name, error);
- return_if_nok (error);
- *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
- } else {
- MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
- *name = g_strdup (p->property->name);
- if (p->property->get)
- *type = mono_method_signature (p->property->get)->ret;
- else
- *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
- }
-}
-
-static void
-get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (field);
- if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
- *name = mono_string_to_utf8_checked (fb->name, error);
- return_if_nok (error);
- *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- } else {
- MonoReflectionField *f = (MonoReflectionField *)field;
- *name = g_strdup (mono_field_get_name (f->field));
- *type = f->field->type;
- }
-}
-
-#else /* DISABLE_REFLECTION_EMIT */
-
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
-{
- /* This is empty */
-}
-
-static gboolean
-is_sre_type_builder (MonoClass *klass)
-{
- return FALSE;
-}
-
-static gboolean
-is_sre_generic_instance (MonoClass *klass)
-{
- return FALSE;
-}
-
-static void
-init_type_builder_generics (MonoObject *type, MonoError *error)
-{
- mono_error_init (error);
-}
-
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-
-static gboolean
-is_sr_mono_field (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoField");
-}
-
-static gboolean
-is_sr_mono_property (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
-}
-
-static gboolean
-is_sr_mono_method (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
-}
-
-static gboolean
-is_sr_mono_cmethod (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
-}
-
-static gboolean
-is_sr_mono_generic_method (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
-}
-
-static gboolean
-is_sr_mono_generic_cmethod (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
-}
-
-gboolean
-mono_class_is_reflection_method_or_constructor (MonoClass *klass)
-{
- return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
-}
-
-static gboolean
-is_usertype (MonoReflectionType *ref)
-{
- MonoClass *klass = mono_object_class (ref);
- return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
-}
-
-static inline MonoBoolean
-is_generic_parameter (MonoType *type)
-{
- return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
-}
-
-static MonoReflectionType*
-mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
-{
- mono_error_init (error);
- if (!type || type->type)
- return type;
-
- if (is_usertype (type)) {
- type = mono_reflection_type_get_underlying_system_type (type, error);
- return_val_if_nok (error, NULL);
- if (is_usertype (type)) {
- mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
- return NULL;
- }
- }
-
- return type;
-}
-/**
- * encode_cattr_value:
- * Encode a value in a custom attribute stream of bytes.
- * The value to encode is either supplied as an object in argument val
- * (valuetypes are boxed), or as a pointer to the data in the
- * argument argval.
- * @type represents the type of the value
- * @buffer is the start of the buffer
- * @p the current position in the buffer
- * @buflen contains the size of the buffer and is used to return the new buffer size
- * if this needs to be realloced.
- * @retbuffer and @retp return the start and the position of the buffer
- * @error set on error.
- */
-static void
-encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
-{
- MonoTypeEnum simple_type;
-
- mono_error_init (error);
- if ((p-buffer) + 10 >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- if (!argval)
- argval = ((char*)arg + sizeof (MonoObject));
- simple_type = type->type;
-handle_enum:
- switch (simple_type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- *p++ = *argval;
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- swap_with_size (p, argval, 2, 1);
- p += 2;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- swap_with_size (p, argval, 4, 1);
- p += 4;
- break;
- case MONO_TYPE_R8:
- swap_with_size (p, argval, 8, 1);
- p += 8;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- swap_with_size (p, argval, 8, 1);
- p += 8;
- break;
- case MONO_TYPE_VALUETYPE:
- if (type->data.klass->enumtype) {
- simple_type = mono_class_enum_basetype (type->data.klass)->type;
- goto handle_enum;
- } else {
- g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
- }
- break;
- case MONO_TYPE_STRING: {
- char *str;
- guint32 slen;
- if (!arg) {
- *p++ = 0xFF;
- break;
- }
- str = mono_string_to_utf8_checked ((MonoString*)arg, error);
- return_if_nok (error);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- break;
- }
- case MONO_TYPE_CLASS: {
- char *str;
- guint32 slen;
- MonoType *arg_type;
- if (!arg) {
- *p++ = 0xFF;
- break;
- }
-handle_type:
- arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
- return_if_nok (error);
-
- str = type_get_qualified_name (arg_type, NULL);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- break;
- }
- case MONO_TYPE_SZARRAY: {
- int len, i;
- MonoClass *eclass, *arg_eclass;
-
- if (!arg) {
- *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
- break;
- }
- len = mono_array_length ((MonoArray*)arg);
- *p++ = len & 0xff;
- *p++ = (len >> 8) & 0xff;
- *p++ = (len >> 16) & 0xff;
- *p++ = (len >> 24) & 0xff;
- *retp = p;
- *retbuffer = buffer;
- eclass = type->data.klass;
- arg_eclass = mono_object_class (arg)->element_class;
-
- if (!eclass) {
- /* Happens when we are called from the MONO_TYPE_OBJECT case below */
- eclass = mono_defaults.object_class;
- }
- if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
- char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
- int elsize = mono_class_array_element_size (arg_eclass);
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
- return_if_nok (error);
- elptr += elsize;
- }
- } else if (eclass->valuetype && arg_eclass->valuetype) {
- char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
- int elsize = mono_class_array_element_size (eclass);
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
- return_if_nok (error);
- elptr += elsize;
- }
- } else {
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
- return_if_nok (error);
- }
- }
- break;
- }
- case MONO_TYPE_OBJECT: {
- MonoClass *klass;
- char *str;
- guint32 slen;
-
- /*
- * The parameter type is 'object' but the type of the actual
- * argument is not. So we have to add type information to the blob
- * too. This is completely undocumented in the spec.
- */
-
- if (arg == NULL) {
- *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
- *p++ = 0xFF;
- break;
- }
-
- klass = mono_object_class (arg);
-
- if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
- *p++ = 0x50;
- goto handle_type;
- } else {
- return_if_nok (error);
- }
-
- if (klass->enumtype) {
- *p++ = 0x55;
- } else if (klass == mono_defaults.string_class) {
- simple_type = MONO_TYPE_STRING;
- *p++ = 0x0E;
- goto handle_enum;
- } else if (klass->rank == 1) {
- *p++ = 0x1D;
- if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
- /* See Partition II, Appendix B3 */
- *p++ = 0x51;
- else
- *p++ = klass->element_class->byval_arg.type;
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
- return_if_nok (error);
- break;
- } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
- *p++ = simple_type = klass->byval_arg.type;
- goto handle_enum;
- } else {
- g_error ("unhandled type in custom attr");
- }
- str = type_get_qualified_name (mono_class_get_type(klass), NULL);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- simple_type = mono_class_enum_basetype (klass)->type;
- goto handle_enum;
- }
- default:
- g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
- }
- *retp = p;
- *retbuffer = buffer;
-}
-
-static void
-encode_field_or_prop_type (MonoType *type, char *p, char **retp)
-{
- if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (type, NULL);
- int slen = strlen (str);
-
- *p++ = 0x55;
- /*
- * This seems to be optional...
- * *p++ = 0x80;
- */
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- } else if (type->type == MONO_TYPE_OBJECT) {
- *p++ = 0x51;
- } else if (type->type == MONO_TYPE_CLASS) {
- /* it should be a type: encode_cattr_value () has the check */
- *p++ = 0x50;
- } else {
- mono_metadata_encode_value (type->type, p, &p);
- if (type->type == MONO_TYPE_SZARRAY)
- /* See the examples in Partition VI, Annex B */
- encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
- }
-
- *retp = p;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static void
-encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
-{
- int len;
-
- mono_error_init (error);
-
- /* Preallocate a large enough buffer */
- if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (type, NULL);
- len = strlen (str);
- g_free (str);
- } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
- len = strlen (str);
- g_free (str);
- } else {
- len = 0;
- }
- len += strlen (name);
-
- if ((p-buffer) + 20 + len >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += len;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
-
- encode_field_or_prop_type (type, p, &p);
-
- len = strlen (name);
- mono_metadata_encode_value (len, p, &p);
- memcpy (p, name, len);
- p += len;
- encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
- return_if_nok (error);
- *retp = p;
- *retbuffer = buffer;
-}
-
-/**
- * mono_reflection_get_custom_attrs_blob:
- * @ctor: custom attribute constructor
- * @ctorArgs: arguments o the constructor
- * @properties:
- * @propValues:
- * @fields:
- * @fieldValues:
- *
- * Creates the blob of data that needs to be saved in the metadata and that represents
- * the custom attributed described by @ctor, @ctorArgs etc.
- * Returns: a Byte array representing the blob of data.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
-{
- MonoError error;
- MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_custom_attrs_blob_checked:
- * @ctor: custom attribute constructor
- * @ctorArgs: arguments o the constructor
- * @properties:
- * @propValues:
- * @fields:
- * @fieldValues:
- * @error: set on error
- *
- * Creates the blob of data that needs to be saved in the metadata and that represents
- * the custom attributed described by @ctor, @ctorArgs etc.
- * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
-{
- MonoArray *result = NULL;
- MonoMethodSignature *sig;
- MonoObject *arg;
- char *buffer, *p;
- guint32 buflen, i;
-
- mono_error_init (error);
-
- if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
- /* sig is freed later so allocate it in the heap */
- sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
- if (!is_ok (error)) {
- g_free (sig);
- return NULL;
- }
- } else {
- sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
- }
-
- g_assert (mono_array_length (ctorArgs) == sig->param_count);
- buflen = 256;
- p = buffer = (char *)g_malloc (buflen);
- /* write the prolog */
- *p++ = 1;
- *p++ = 0;
- for (i = 0; i < sig->param_count; ++i) {
- arg = mono_array_get (ctorArgs, MonoObject*, i);
- encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
- if (!is_ok (error)) goto leave;
- }
- i = 0;
- if (properties)
- i += mono_array_length (properties);
- if (fields)
- i += mono_array_length (fields);
- *p++ = i & 0xff;
- *p++ = (i >> 8) & 0xff;
- if (properties) {
- MonoObject *prop;
- for (i = 0; i < mono_array_length (properties); ++i) {
- MonoType *ptype;
- char *pname;
-
- prop = (MonoObject *)mono_array_get (properties, gpointer, i);
- get_prop_name_and_type (prop, &pname, &ptype, error);
- if (!is_ok (error)) goto leave;
- *p++ = 0x54; /* PROPERTY signature */
- encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
- g_free (pname);
- if (!is_ok (error)) goto leave;
- }
- }
-
- if (fields) {
- MonoObject *field;
- for (i = 0; i < mono_array_length (fields); ++i) {
- MonoType *ftype;
- char *fname;
-
- field = (MonoObject *)mono_array_get (fields, gpointer, i);
- get_field_name_and_type (field, &fname, &ftype, error);
- if (!is_ok (error)) goto leave;
- *p++ = 0x53; /* FIELD signature */
- encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
- g_free (fname);
- if (!is_ok (error)) goto leave;
- }
- }
-
- g_assert (p - buffer <= buflen);
- buflen = p - buffer;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error))
- goto leave;
- p = mono_array_addr (result, char, 0);
- memcpy (p, buffer, buflen);
-leave:
- g_free (buffer);
- if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
- g_free (sig);
- return result;
-}
-
-/**
- * reflection_setup_internal_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Creates a MonoClass that represents the TypeBuilder.
- * This is a trick that lets us simplify a lot of reflection code
- * (and will allow us to support Build and Run assemblies easier).
- *
- * Returns TRUE on success. On failure, returns FALSE and sets @error.
- */
-static gboolean
-reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- MonoClass *klass, *parent;
-
- mono_error_init (error);
- RESOLVE_TYPE (tb->parent, error);
- return_val_if_nok (error, FALSE);
-
- mono_loader_lock ();
-
- if (tb->parent) {
- MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- /* check so we can compile corlib correctly */
- if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
- /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
- parent = parent_type->data.klass;
- } else {
- parent = mono_class_from_mono_type (parent_type);
- }
- } else {
- parent = NULL;
- }
-
- /* the type has already being created: it means we just have to change the parent */
- if (tb->type.type) {
- klass = mono_class_from_mono_type (tb->type.type);
- klass->parent = NULL;
- /* fool mono_class_setup_parent */
- klass->supertypes = NULL;
- mono_class_setup_parent (klass, parent);
- mono_class_setup_mono_type (klass);
- mono_loader_unlock ();
- return TRUE;
- }
-
- klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
-
- klass->image = &tb->module->dynamic_image->image;
-
- klass->inited = 1; /* we lie to the runtime */
- klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
- if (!is_ok (error))
- goto failure;
- klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
- if (!is_ok (error))
- goto failure;
- klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
- klass->flags = tb->attrs;
-
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
-
- klass->element_class = klass;
-
- if (mono_class_get_ref_info (klass) == NULL) {
-
- mono_class_set_ref_info (klass, tb);
-
- /* Put into cache so mono_class_get_checked () will find it.
- Skip nested types as those should not be available on the global scope. */
- if (!tb->nesting_type)
- mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
-
- /*
- We must register all types as we cannot rely on the name_cache hashtable since we find the class
- by performing a mono_class_get which does the full resolution.
-
- Working around this semantics would require us to write a lot of code for no clear advantage.
- */
- mono_image_append_class_to_reflection_info_set (klass);
- } else {
- g_assert (mono_class_get_ref_info (klass) == tb);
- }
-
- register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
-
- if (parent != NULL) {
- mono_class_setup_parent (klass, parent);
- } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
- const char *old_n = klass->name;
- /* trick to get relative numbering right when compiling corlib */
- klass->name = "BuildingObject";
- mono_class_setup_parent (klass, mono_defaults.object_class);
- klass->name = old_n;
- }
-
- if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
- (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
- (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
- klass->instance_size = sizeof (MonoObject);
- klass->size_inited = 1;
- mono_class_setup_vtable_general (klass, NULL, 0, NULL);
- }
-
- mono_class_setup_mono_type (klass);
-
- mono_class_setup_supertypes (klass);
-
- /*
- * FIXME: handle interfaces.
- */
-
- tb->type.type = &klass->byval_arg;
-
- if (tb->nesting_type) {
- g_assert (tb->nesting_type->type);
- MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
- if (!is_ok (error)) goto failure;
- klass->nested_in = mono_class_from_mono_type (nesting_type);
- }
-
- /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
-
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
-
- mono_loader_unlock ();
- return TRUE;
-
-failure:
- mono_loader_unlock ();
- return FALSE;
-}
-
-/**
- * ves_icall_TypeBuilder_setup_internal_class:
- * @tb: a TypeBuilder object
- *
- * (icall)
- * Creates a MonoClass that represents the TypeBuilder.
- * This is a trick that lets us simplify a lot of reflection code
- * (and will allow us to support Build and Run assemblies easier).
- *
- */
-void
-ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
-{
- MonoError error;
- (void) reflection_setup_internal_class (tb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-/*
- * ves_icall_TypeBuilder_setup_generic_class:
- * @tb: a TypeBuilder object
- *
- * Setup the generic class before adding the first generic parameter.
- */
-void
-ves_icall_TypeBuilder_setup_generic_class (MonoReflectionTypeBuilder *tb)
-{
-}
-
-/**
- * mono_reflection_create_generic_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Creates the generic class after all generic parameters have been added.
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-static gboolean
-mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
-
- MonoClass *klass;
- int count, i;
-
- mono_error_init (error);
-
- klass = mono_class_from_mono_type (tb->type.type);
-
- count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
-
- if (klass->generic_container || (count == 0))
- return TRUE;
-
- g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
-
- klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
-
- klass->generic_container->owner.klass = klass;
- klass->generic_container->type_argc = count;
- klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
-
- klass->is_generic = 1;
-
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
- MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
- return_val_if_nok (error, FALSE);
- MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
- klass->generic_container->type_params [i] = *param;
- /*Make sure we are a diferent type instance */
- klass->generic_container->type_params [i].param.owner = klass->generic_container;
- klass->generic_container->type_params [i].info.pklass = NULL;
- klass->generic_container->type_params [i].info.flags = gparam->attrs;
-
- g_assert (klass->generic_container->type_params [i].param.owner);
- }
-
- klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
- return TRUE;
-}
-
-/**
- * reflection_create_internal_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Actually create the MonoClass that is associated with the TypeBuilder.
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-static gboolean
-reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- MonoClass *klass;
-
- mono_error_init (error);
- klass = mono_class_from_mono_type (tb->type.type);
-
- mono_loader_lock ();
- if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
- MonoReflectionFieldBuilder *fb;
- MonoClass *ec;
- MonoType *enum_basetype;
-
- g_assert (tb->fields != NULL);
- g_assert (mono_array_length (tb->fields) >= 1);
-
- fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
-
- MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- if (!mono_type_is_valid_enum_basetype (field_type)) {
- mono_loader_unlock ();
- return TRUE;
- }
-
- enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- klass->element_class = mono_class_from_mono_type (enum_basetype);
- if (!klass->element_class)
- klass->element_class = mono_class_from_mono_type (enum_basetype);
-
- /*
- * get the element_class from the current corlib.
- */
- ec = default_class_from_mono_type (enum_basetype);
- klass->instance_size = ec->instance_size;
- klass->size_inited = 1;
- /*
- * this is almost safe to do with enums and it's needed to be able
- * to create objects of the enum type (for use in SetConstant).
- */
- /* FIXME: Does this mean enums can't have method overrides ? */
- mono_class_setup_vtable_general (klass, NULL, 0, NULL);
- }
- mono_loader_unlock ();
- return TRUE;
-}
-
-/**
- * ves_icall_TypeBuilder_create_internal_class:
- * @tb: a TypeBuilder object
- *
- * (icall)
- * Actually create the MonoClass that is associated with the TypeBuilder.
- */
-void
-ves_icall_TypeBuilder_create_internal_class (MonoReflectionTypeBuilder *tb)
-{
- MonoError error;
- (void) reflection_create_internal_class (tb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static MonoMarshalSpec*
-mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
- MonoReflectionMarshal *minfo, MonoError *error)
-{
- MonoMarshalSpec *res;
-
- mono_error_init (error);
-
- res = image_g_new0 (image, MonoMarshalSpec, 1);
- res->native = (MonoMarshalNative)minfo->type;
-
- switch (minfo->type) {
- case MONO_NATIVE_LPARRAY:
- res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
- if (minfo->has_size) {
- res->data.array_data.param_num = minfo->param_num;
- res->data.array_data.num_elem = minfo->count;
- res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
- }
- else {
- res->data.array_data.param_num = -1;
- res->data.array_data.num_elem = -1;
- res->data.array_data.elem_mult = -1;
- }
- break;
-
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- res->data.array_data.num_elem = minfo->count;
- break;
-
- case MONO_NATIVE_CUSTOM:
- if (minfo->marshaltyperef) {
- MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
- if (!is_ok (error)) {
- image_g_free (image, res);
- return NULL;
- }
- res->data.custom_data.custom_name =
- type_get_fully_qualified_name (marshaltyperef);
- }
- if (minfo->mcookie) {
- res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
- if (!is_ok (error)) {
- image_g_free (image, res);
- return NULL;
- }
- }
- break;
-
- default:
- break;
- }
-
- return res;
-}
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-MonoReflectionMarshalAsAttribute*
-mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
- MonoMarshalSpec *spec, MonoError *error)
-{
- MonoReflectionType *rt;
- MonoReflectionMarshalAsAttribute *minfo;
- MonoType *mtype;
-
- mono_error_init (error);
-
- minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
- if (!minfo)
- return NULL;
- minfo->utype = spec->native;
-
- switch (minfo->utype) {
- case MONO_NATIVE_LPARRAY:
- minfo->array_subtype = spec->data.array_data.elem_type;
- minfo->size_const = spec->data.array_data.num_elem;
- if (spec->data.array_data.param_num != -1)
- minfo->size_param_index = spec->data.array_data.param_num;
- break;
-
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- minfo->size_const = spec->data.array_data.num_elem;
- break;
-
- case MONO_NATIVE_CUSTOM:
- if (spec->data.custom_data.custom_name) {
- mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
- return_val_if_nok (error, NULL);
-
- if (mtype) {
- rt = mono_type_get_object_checked (domain, mtype, error);
- if (!rt)
- return NULL;
-
- MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
- }
-
- MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
- }
- if (spec->data.custom_data.cookie)
- MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
- break;
-
- default:
- break;
- }
-
- return minfo;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoMethod*
-reflection_methodbuilder_to_mono_method (MonoClass *klass,
- ReflectionMethodBuilder *rmb,
- MonoMethodSignature *sig,
- MonoError *error)
-{
- MonoMethod *m;
- MonoMethodWrapper *wrapperm;
- MonoMarshalSpec **specs;
- MonoReflectionMethodAux *method_aux;
- MonoImage *image;
- gboolean dynamic;
- int i;
-
- mono_error_init (error);
- /*
- * Methods created using a MethodBuilder should have their memory allocated
- * inside the image mempool, while dynamic methods should have their memory
- * malloc'd.
- */
- dynamic = rmb->refs != NULL;
- image = dynamic ? NULL : klass->image;
-
- if (!dynamic)
- g_assert (!klass->generic_class);
-
- mono_loader_lock ();
-
- if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
- m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
- else
- m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
-
- wrapperm = (MonoMethodWrapper*)m;
-
- m->dynamic = dynamic;
- m->slot = -1;
- m->flags = rmb->attrs;
- m->iflags = rmb->iattrs;
- m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
- m->klass = klass;
- m->signature = sig;
- m->sre_method = TRUE;
- m->skip_visibility = rmb->skip_visibility;
- if (rmb->table_idx)
- m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
-
- if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
- m->string_ctor = 1;
-
- m->signature->pinvoke = 1;
- } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
- m->signature->pinvoke = 1;
-
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
-
- method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
- mono_error_assert_ok (error);
- method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
- mono_error_assert_ok (error);
-
- ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
-
- if (image_is_dynamic (klass->image))
- g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
-
- mono_loader_unlock ();
-
- return m;
- } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
- !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
- MonoMethodHeader *header;
- guint32 code_size;
- gint32 max_stack, i;
- gint32 num_locals = 0;
- gint32 num_clauses = 0;
- guint8 *code;
-
- if (rmb->ilgen) {
- code = mono_array_addr (rmb->ilgen->code, guint8, 0);
- code_size = rmb->ilgen->code_len;
- max_stack = rmb->ilgen->max_stack;
- num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
- if (rmb->ilgen->ex_handlers)
- num_clauses = method_count_clauses (rmb->ilgen);
- } else {
- if (rmb->code) {
- code = mono_array_addr (rmb->code, guint8, 0);
- code_size = mono_array_length (rmb->code);
- /* we probably need to run a verifier on the code... */
- max_stack = 8;
- }
- else {
- code = NULL;
- code_size = 0;
- max_stack = 8;
- }
- }
-
- header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
- header->code_size = code_size;
- header->code = (const unsigned char *)image_g_malloc (image, code_size);
- memcpy ((char*)header->code, code, code_size);
- header->max_stack = max_stack;
- header->init_locals = rmb->init_locals;
- header->num_locals = num_locals;
-
- for (i = 0; i < num_locals; ++i) {
- MonoReflectionLocalBuilder *lb =
- mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
-
- header->locals [i] = image_g_new0 (image, MonoType, 1);
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
- mono_error_assert_ok (error);
- memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
- }
-
- header->num_clauses = num_clauses;
- if (num_clauses) {
- header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
- rmb->ilgen, num_clauses, error);
- mono_error_assert_ok (error);
- }
-
- wrapperm->header = header;
- }
-
- if (rmb->generic_params) {
- int count = mono_array_length (rmb->generic_params);
- MonoGenericContainer *container = rmb->generic_container;
-
- g_assert (container);
-
- container->type_argc = count;
- container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
- container->owner.method = m;
- container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
-
- m->is_generic = TRUE;
- mono_method_set_generic_container (m, container);
-
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gp =
- mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
- MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
- mono_error_assert_ok (error);
- MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
- container->type_params [i] = *param;
- }
-
- /*
- * The method signature might have pointers to generic parameters that belong to other methods.
- * This is a valid SRE case, but the resulting method signature must be encoded using the proper
- * generic parameters.
- */
- for (i = 0; i < m->signature->param_count; ++i) {
- MonoType *t = m->signature->params [i];
- if (t->type == MONO_TYPE_MVAR) {
- MonoGenericParam *gparam = t->data.generic_param;
- if (gparam->num < count) {
- m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
- m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
- }
-
- }
- }
-
- if (klass->generic_container) {
- container->parent = klass->generic_container;
- container->context.class_inst = klass->generic_container->context.class_inst;
- }
- container->context.method_inst = mono_get_shared_generic_inst (container);
- }
-
- if (rmb->refs) {
- MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
- int i;
- void **data;
-
- m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
-
- mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
- data [0] = GUINT_TO_POINTER (rmb->nrefs);
- for (i = 0; i < rmb->nrefs; ++i)
- data [i + 1] = rmb->refs [i];
- }
-
- method_aux = NULL;
-
- /* Parameter info */
- if (rmb->pinfo) {
- if (!method_aux)
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
- method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
- for (i = 0; i <= m->signature->param_count; ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
- if ((i > 0) && (pb->attrs)) {
- /* Make a copy since it might point to a shared type structure */
- m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
- m->signature->params [i - 1]->attrs = pb->attrs;
- }
-
- if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
- MonoDynamicImage *assembly;
- guint32 idx, len;
- MonoTypeEnum def_type;
- char *p;
- const char *p2;
-
- if (!method_aux->param_defaults) {
- method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
- method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
- }
- assembly = (MonoDynamicImage*)klass->image;
- idx = encode_constant (assembly, pb->def_value, &def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
- method_aux->param_default_types [i] = def_type;
- memcpy ((gpointer)method_aux->param_defaults [i], p, len);
- }
-
- if (pb->name) {
- method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
- mono_error_assert_ok (error);
- }
- if (pb->cattrs) {
- if (!method_aux->param_cattr)
- method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
- method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
- }
- }
- }
- }
-
- /* Parameter marshalling */
- specs = NULL;
- if (rmb->pinfo)
- for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
- if (pb->marshal_info) {
- if (specs == NULL)
- specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
- specs [pb->position] =
- mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- image_g_free (image, specs);
- /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
- return NULL;
- }
- }
- }
- }
- if (specs != NULL) {
- if (!method_aux)
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
- method_aux->param_marshall = specs;
- }
-
- if (image_is_dynamic (klass->image) && method_aux)
- g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
-
- mono_loader_unlock ();
-
- return m;
-}
-
-static MonoMethod*
-ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
-{
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
-
- mono_loader_lock ();
- g_assert (klass->image != NULL);
- sig = ctor_builder_to_signature (klass->image, mb, error);
- mono_loader_unlock ();
- return_val_if_nok (error, NULL);
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return NULL;
-
- mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
- mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
-
- /* If we are in a generic class, we might be called multiple times from inflate_method */
- if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
- }
-
- return mb->mhandle;
-}
-
-static MonoMethod*
-methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
-{
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- mono_loader_lock ();
- g_assert (klass->image != NULL);
- sig = method_builder_to_signature (klass->image, mb, error);
- mono_loader_unlock ();
- return_val_if_nok (error, NULL);
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- return NULL;
-
- mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
- mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
-
- /* If we are in a generic class, we might be called multiple times from inflate_method */
- if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
- }
- return mb->mhandle;
-}
-
-static MonoClassField*
-fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
-{
- MonoClassField *field;
- MonoType *custom;
-
- mono_error_init (error);
-
- field = g_new0 (MonoClassField, 1);
-
- field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
- mono_error_assert_ok (error);
- if (fb->attrs || fb->modreq || fb->modopt) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- field->type = mono_metadata_type_dup (NULL, type);
- field->type->attrs = fb->attrs;
-
- g_assert (image_is_dynamic (klass->image));
- custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
- g_free (field->type);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- field->type = mono_metadata_type_dup (klass->image, custom);
- g_free (custom);
- } else {
- field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- }
- if (fb->offset != -1)
- field->offset = fb->offset;
- field->parent = klass;
- mono_save_custom_attrs (klass->image, field, fb->cattrs);
-
- // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
-
- return field;
-}
-#endif
-
-/**
- * mono_reflection_bind_generic_parameters:
- * @type: a managed type object (which should be some kind of generic (instance? definition?))
- * @type_args: the number of type arguments to bind
- * @types: array of type arguments
- * @error: set on error
- *
- * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
- * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
- */
-MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
-{
- MonoClass *klass;
- MonoReflectionTypeBuilder *tb = NULL;
- gboolean is_dynamic = FALSE;
- MonoClass *geninst;
-
- mono_error_init (error);
-
- mono_loader_lock ();
-
- if (is_sre_type_builder (mono_object_class (type))) {
- tb = (MonoReflectionTypeBuilder *) type;
-
- is_dynamic = TRUE;
- } else if (is_sre_generic_instance (mono_object_class (type))) {
- MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
- MonoReflectionType *gtd = rgi->generic_type;
-
- if (is_sre_type_builder (mono_object_class (gtd))) {
- tb = (MonoReflectionTypeBuilder *)gtd;
- is_dynamic = TRUE;
- }
- }
-
- /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
- if (tb && tb->generic_container) {
- if (!mono_reflection_create_generic_class (tb, error)) {
- mono_loader_unlock ();
- return NULL;
- }
- }
-
- MonoType *t = mono_reflection_type_get_handle (type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return NULL;
- }
-
- klass = mono_class_from_mono_type (t);
- if (!klass->generic_container) {
- mono_loader_unlock ();
- mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
- return NULL;
- }
-
- if (klass->wastypebuilder) {
- tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
-
- is_dynamic = TRUE;
- }
-
- mono_loader_unlock ();
-
- geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
-
- return &geninst->byval_arg;
-}
-
-MonoClass*
-mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
-{
- MonoGenericClass *gclass;
- MonoGenericInst *inst;
-
- g_assert (klass->generic_container);
-
- inst = mono_metadata_get_generic_inst (type_argc, types);
- gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
-
- return mono_generic_class_get_class (gclass);
-}
-
-static MonoReflectionMethod*
-reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
-{
- MonoClass *klass;
- MonoMethod *method, *inflated;
- MonoMethodInflated *imethod;
- MonoGenericContext tmp_context;
- MonoGenericInst *ginst;
- MonoType **type_argv;
- int count, i;
-
- mono_error_init (error);
-
- /*FIXME but this no longer should happen*/
- if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
-#ifndef DISABLE_REFLECTION_EMIT
- MonoReflectionMethodBuilder *mb = NULL;
- MonoType *tb;
- MonoClass *klass;
-
- mb = (MonoReflectionMethodBuilder *) rmethod;
- tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (tb);
-
- method = methodbuilder_to_mono_method (klass, mb, error);
- return_val_if_nok (error, NULL);
-#else
- g_assert_not_reached ();
- method = NULL;
-#endif
- } else {
- method = rmethod->method;
- }
-
- klass = method->klass;
-
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- count = mono_method_signature (method)->generic_param_count;
- if (count != mono_array_length (types))
- return NULL;
-
- type_argv = g_new0 (MonoType *, count);
- for (i = 0; i < count; i++) {
- MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
- type_argv [i] = mono_reflection_type_get_handle (garg, error);
- if (!is_ok (error)) {
- g_free (type_argv);
- return NULL;
- }
- }
- ginst = mono_metadata_get_generic_inst (count, type_argv);
- g_free (type_argv);
-
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
- tmp_context.method_inst = ginst;
-
- inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
- mono_error_assert_ok (error);
- imethod = (MonoMethodInflated *) inflated;
-
- /*FIXME but I think this is no longer necessary*/
- if (image_is_dynamic (method->klass->image)) {
- MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
- /*
- * This table maps metadata structures representing inflated methods/fields
- * to the reflection objects representing their generic definitions.
- */
- mono_image_lock ((MonoImage*)image);
- mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
- mono_image_unlock ((MonoImage*)image);
- }
-
- if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
- mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
- return NULL;
- }
-
- MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
- return ret;
-}
-
-MonoReflectionMethod*
-ves_icall_MethodBuilder_MakeGenericMethod (MonoReflectionMethod *rmethod, MonoArray *types)
-{
- MonoError error;
- MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-MonoReflectionMethod*
-ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
-{
- MonoError error;
- MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-static MonoMethod *
-inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
-{
- MonoMethodInflated *imethod;
- MonoGenericContext *context;
- int i;
-
- /*
- * With generic code sharing the klass might not be inflated.
- * This can happen because classes inflated with their own
- * type arguments are "normalized" to the uninflated class.
- */
- if (!klass->generic_class)
- return method;
-
- context = mono_class_get_context (klass);
-
- if (klass->method.count && klass->methods) {
- /* Find the already created inflated method */
- for (i = 0; i < klass->method.count; ++i) {
- g_assert (klass->methods [i]->is_inflated);
- if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
- break;
- }
- g_assert (i < klass->method.count);
- imethod = (MonoMethodInflated*)klass->methods [i];
- } else {
- MonoError error;
- imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
- mono_error_assert_ok (&error);
- }
-
- if (method->is_generic && image_is_dynamic (method->klass->image)) {
- MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
-
- mono_image_lock ((MonoImage*)image);
- mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
- mono_image_unlock ((MonoImage*)image);
- }
- return (MonoMethod *) imethod;
-}
-
-static MonoMethod *
-inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
-{
- MonoMethod *method;
- MonoClass *gklass;
-
- mono_error_init (error);
-
- MonoClass *type_class = mono_object_class (type);
-
- if (is_sre_generic_instance (type_class)) {
- MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
- MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
- return_val_if_nok (error, NULL);
- gklass = mono_class_from_mono_type (generic_type);
- } else if (is_sre_type_builder (type_class)) {
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_val_if_nok (error, NULL);
- gklass = mono_class_from_mono_type (t);
- } else if (type->type) {
- gklass = mono_class_from_mono_type (type->type);
- gklass = mono_class_get_generic_type_definition (gklass);
- } else {
- g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
- }
-
- if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
- if (((MonoReflectionMethodBuilder*)obj)->mhandle)
- method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
- else {
- method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
- if (!method)
- return NULL;
- }
- else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
- method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
- if (!method)
- return NULL;
- } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
- method = ((MonoReflectionMethod *) obj)->method;
- else {
- method = NULL; /* prevent compiler warning */
- g_error ("can't handle type %s", obj->vtable->klass->name);
- }
-
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_val_if_nok (error, NULL);
- return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
-}
-
-/*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
-static gboolean
-reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
-{
- MonoGenericClass *gclass;
- MonoDynamicGenericClass *dgclass;
- MonoClass *klass, *gklass;
- MonoType *gtype;
- int i;
-
- mono_error_init (error);
-
- gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
- return_val_if_nok (error, FALSE);
- klass = mono_class_from_mono_type (gtype);
- g_assert (gtype->type == MONO_TYPE_GENERICINST);
- gclass = gtype->data.generic_class;
-
- if (!gclass->is_dynamic)
- return TRUE;
-
- dgclass = (MonoDynamicGenericClass *) gclass;
-
- if (dgclass->initialized)
- return TRUE;
-
- gklass = gclass->container_class;
- mono_class_init (gklass);
-
- dgclass->count_fields = fields ? mono_array_length (fields) : 0;
-
- dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
- dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
- dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
-
- for (i = 0; i < dgclass->count_fields; i++) {
- MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
- MonoClassField *field, *inflated_field = NULL;
-
- if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
- inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
- return_val_if_nok (error, FALSE);
- } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
- field = ((MonoReflectionField *) obj)->field;
- else {
- field = NULL; /* prevent compiler warning */
- g_assert_not_reached ();
- }
-
- dgclass->fields [i] = *field;
- dgclass->fields [i].parent = klass;
- dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
- field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
- mono_error_assert_ok (error); /* FIXME don't swallow the error */
- dgclass->field_generic_types [i] = field->type;
- MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
- dgclass->field_objects [i] = obj;
-
- if (inflated_field) {
- g_free (inflated_field);
- } else {
- dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
- }
- }
-
- dgclass->initialized = TRUE;
- return TRUE;
-}
-
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
-{
- MonoError error;
- (void) reflection_generic_class_initialize (type, fields, &error);
- mono_error_set_pending_exception (&error);
-}
-
-void
-mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
-{
- MonoDynamicGenericClass *dgclass;
- int i;
-
- g_assert (gclass->is_dynamic);
-
- dgclass = (MonoDynamicGenericClass *)gclass;
-
- for (i = 0; i < dgclass->count_fields; ++i) {
- MonoClassField *field = dgclass->fields + i;
- mono_metadata_free_type (field->type);
- MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
+ assembly->name = p;
+ while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
+ p++;
+ if (quoted) {
+ if (*p != '"')
+ return 1;
+ *p = 0;
+ p++;
}
-}
-
-/**
- * fix_partial_generic_class:
- * @klass: a generic instantiation MonoClass
- * @error: set on error
- *
- * Assumes that the generic container of @klass has its vtable
- * initialized, and updates the parent class, insterfaces, methods and
- * fields of @klass by inflating the types using the generic context.
- *
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-static gboolean
-fix_partial_generic_class (MonoClass *klass, MonoError *error)
-{
- MonoClass *gklass = klass->generic_class->container_class;
- MonoDynamicGenericClass *dgclass;
- int i;
-
- mono_error_init (error);
-
- if (klass->wastypebuilder)
- return TRUE;
-
- dgclass = (MonoDynamicGenericClass *) klass->generic_class;
- if (klass->parent != gklass->parent) {
- MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
- if (mono_error_ok (error)) {
- MonoClass *parent = mono_class_from_mono_type (parent_type);
- mono_metadata_free_type (parent_type);
- if (parent != klass->parent) {
- /*fool mono_class_setup_parent*/
- klass->supertypes = NULL;
- mono_class_setup_parent (klass, parent);
+ if (*p != ',')
+ return 1;
+ *p = 0;
+ /* Remove trailing whitespace */
+ s = p - 1;
+ while (*s && g_ascii_isspace (*s))
+ *s-- = 0;
+ p ++;
+ while (g_ascii_isspace (*p))
+ p++;
+ while (*p) {
+ if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
+ p += 8;
+ assembly->major = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->minor = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->build = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->revision = strtoul (p, &s, 10);
+ if (s == p)
+ return 1;
+ p = s;
+ } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
+ p += 8;
+ if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
+ assembly->culture = "";
+ p += 7;
+ } else {
+ assembly->culture = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ }
+ } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
+ p += 15;
+ if (strncmp (p, "null", 4) == 0) {
+ p += 4;
+ } else {
+ int len;
+ gchar *start = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ len = (p - start + 1);
+ if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
+ len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
+ g_strlcpy ((char*)assembly->public_key_token, start, len);
}
} else {
- if (gklass->wastypebuilder)
- klass->wastypebuilder = TRUE;
- return FALSE;
- }
- }
-
- if (!dgclass->initialized)
- return TRUE;
-
- if (klass->method.count != gklass->method.count) {
- klass->method.count = gklass->method.count;
- klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
-
- for (i = 0; i < klass->method.count; i++) {
- klass->methods [i] = mono_class_inflate_generic_method_full_checked (
- gklass->methods [i], klass, mono_class_get_context (klass), error);
- mono_error_assert_ok (error);
- }
- }
-
- if (klass->interface_count && klass->interface_count != gklass->interface_count) {
- klass->interface_count = gklass->interface_count;
- klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
- klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
-
- for (i = 0; i < gklass->interface_count; ++i) {
- MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
- return_val_if_nok (error, FALSE);
-
- klass->interfaces [i] = mono_class_from_mono_type (iface_type);
- mono_metadata_free_type (iface_type);
-
- if (!ensure_runtime_vtable (klass->interfaces [i], error))
- return FALSE;
+ while (*p && *p != ',')
+ p++;
}
- klass->interfaces_inited = 1;
- }
-
- if (klass->field.count != gklass->field.count) {
- klass->field.count = gklass->field.count;
- klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
-
- for (i = 0; i < klass->field.count; i++) {
- klass->fields [i] = gklass->fields [i];
- klass->fields [i].parent = klass;
- klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
- return_val_if_nok (error, FALSE);
+ found_sep = 0;
+ while (g_ascii_isspace (*p) || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
}
+ /* failed */
+ if (!found_sep)
+ return 1;
}
- /*We can only finish with this klass once it's parent has as well*/
- if (gklass->wastypebuilder)
- klass->wastypebuilder = TRUE;
- return TRUE;
+ return 0;
}
-/**
- * ensure_generic_class_runtime_vtable:
- * @klass a generic class
- * @error set on error
+/*
+ * mono_reflection_parse_type:
+ * @name: type name
*
- * Ensures that the generic container of @klass has a vtable and
- * returns TRUE on success. On error returns FALSE and sets @error.
- */
-static gboolean
-ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
-{
- MonoClass *gklass = klass->generic_class->container_class;
-
- mono_error_init (error);
-
- if (!ensure_runtime_vtable (gklass, error))
- return FALSE;
-
- return fix_partial_generic_class (klass, error);
-}
-
-/**
- * ensure_runtime_vtable:
- * @klass the class
- * @error set on error
+ * Parse a type name as accepted by the GetType () method and output the info
+ * extracted in the info structure.
+ * the name param will be mangled, so, make a copy before passing it to this function.
+ * The fields in info will be valid until the memory pointed to by name is valid.
+ *
+ * See also mono_type_get_name () below.
*
- * Ensures that @klass has a vtable and returns TRUE on success. On
- * error returns FALSE and sets @error.
+ * Returns: 0 on parse error.
*/
-static gboolean
-ensure_runtime_vtable (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- int i, num, j;
-
- mono_error_init (error);
-
- if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
- return TRUE;
- if (klass->parent)
- if (!ensure_runtime_vtable (klass->parent, error))
- return FALSE;
-
- if (tb) {
- num = tb->ctors? mono_array_length (tb->ctors): 0;
- num += tb->num_methods;
- klass->method.count = num;
- klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
- num = tb->ctors? mono_array_length (tb->ctors): 0;
- for (i = 0; i < num; ++i) {
- MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
- if (!ctor)
- return FALSE;
- klass->methods [i] = ctor;
- }
- num = tb->num_methods;
- j = i;
- for (i = 0; i < num; ++i) {
- MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
- if (!meth)
- return FALSE;
- klass->methods [j++] = meth;
- }
-
- if (tb->interfaces) {
- klass->interface_count = mono_array_length (tb->interfaces);
- klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
- for (i = 0; i < klass->interface_count; ++i) {
- MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
- return_val_if_nok (error, FALSE);
- klass->interfaces [i] = mono_class_from_mono_type (iface);
- if (!ensure_runtime_vtable (klass->interfaces [i], error))
- return FALSE;
- }
- klass->interfaces_inited = 1;
- }
- } else if (klass->generic_class){
- if (!ensure_generic_class_runtime_vtable (klass, error)) {
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- return FALSE;
- }
- }
-
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- int slot_num = 0;
- for (i = 0; i < klass->method.count; ++i) {
- MonoMethod *im = klass->methods [i];
- if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
- im->slot = slot_num++;
- }
-
- klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
- mono_class_setup_interface_offsets (klass);
- mono_class_setup_interface_id (klass);
- }
-
- /*
- * The generic vtable is needed even if image->run is not set since some
- * runtime code like ves_icall_Type_GetMethodsByName depends on
- * method->slot being defined.
- */
-
- /*
- * tb->methods could not be freed since it is used for determining
- * overrides during dynamic vtable construction.
- */
-
- return TRUE;
-}
-
-static MonoMethod*
-mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (method);
- if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
- MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
- return sr_method->method;
- }
- if (is_sre_method_builder (klass)) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
- return mb->mhandle;
- }
- if (is_sre_method_on_tb_inst (klass)) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
- MonoMethod *result;
- /*FIXME move this to a proper method and unify with resolve_object*/
- if (m->method_args) {
- result = mono_reflection_method_on_tb_inst_get_handle (m, error);
- } else {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, NULL);
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *mono_method;
-
- if (is_sre_method_builder (mono_object_class (m->mb)))
- mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
- else if (is_sr_mono_method (mono_object_class (m->mb)))
- mono_method = ((MonoReflectionMethod *)m->mb)->method;
- else
- g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
-
- result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
- }
- return result;
- }
-
- g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
- return NULL;
-}
-
-void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
+static int
+_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
+ MonoTypeNameParse *info)
{
- MonoReflectionTypeBuilder *tb;
- int i, j, onum;
- MonoReflectionMethod *m;
-
- mono_error_init (error);
- *overrides = NULL;
- *num_overrides = 0;
-
- g_assert (image_is_dynamic (klass->image));
-
- if (!mono_class_get_ref_info (klass))
- return;
-
- g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
-
- tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
-
- onum = 0;
- if (tb->methods) {
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_methods)
- onum += mono_array_length (mb->override_methods);
- }
- }
-
- if (onum) {
- *overrides = g_new0 (MonoMethod*, onum * 2);
+ char *start, *p, *w, *last_point, *startn;
+ int in_modifiers = 0;
+ int isbyref = 0, rank = 0, isptr = 0;
- onum = 0;
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_methods) {
- for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
- m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
+ start = p = w = name;
- (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
- return_if_nok (error);
- (*overrides) [onum * 2 + 1] = mb->mhandle;
+ //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
+ memset (&info->assembly, 0, sizeof (MonoAssemblyName));
+ info->name = info->name_space = NULL;
+ info->nested = NULL;
+ info->modifiers = NULL;
+ info->type_arguments = NULL;
- g_assert (mb->mhandle);
+ /* last_point separates the namespace from the name */
+ last_point = NULL;
+ /* Skips spaces */
+ while (*p == ' ') p++, start++, w++, name++;
- onum ++;
- }
+ while (*p) {
+ switch (*p) {
+ case '+':
+ *p = 0; /* NULL terminate the name */
+ startn = p + 1;
+ info->nested = g_list_append (info->nested, startn);
+ /* we have parsed the nesting namespace + name */
+ if (info->name)
+ break;
+ if (last_point) {
+ info->name_space = start;
+ *last_point = 0;
+ info->name = last_point + 1;
+ } else {
+ info->name_space = (char *)"";
+ info->name = start;
}
+ break;
+ case '.':
+ last_point = p;
+ break;
+ case '\\':
+ ++p;
+ break;
+ case '&':
+ case '*':
+ case '[':
+ case ',':
+ case ']':
+ in_modifiers = 1;
+ break;
+ default:
+ break;
}
- }
-
- *num_overrides = onum;
-}
-
-static void
-typebuilder_setup_fields (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionFieldBuilder *fb;
- MonoClassField *field;
- MonoImage *image = klass->image;
- const char *p, *p2;
- int i;
- guint32 len, idx, real_size = 0;
-
- klass->field.count = tb->num_fields;
- klass->field.first = 0;
-
- mono_error_init (error);
-
- if (tb->class_size) {
- if ((tb->packing_size & 0xffffff00) != 0) {
- char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
- return;
- }
- klass->packing_size = tb->packing_size;
- real_size = klass->instance_size + tb->class_size;
- }
-
- if (!klass->field.count) {
- klass->instance_size = MAX (klass->instance_size, real_size);
- return;
+ if (in_modifiers)
+ break;
+ // *w++ = *p++;
+ p++;
}
- klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
- mono_class_alloc_ext (klass);
- klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
- /*
- This is, guess what, a hack.
- The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
- On the static path no field class is resolved, only types are built. This is the right thing to do
- but we suck.
- Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
- */
- klass->size_inited = 1;
-
- for (i = 0; i < klass->field.count; ++i) {
- MonoArray *rva_data;
- fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
- field = &klass->fields [i];
- field->name = mono_string_to_utf8_image (image, fb->name, error);
- if (!mono_error_ok (error))
- return;
- if (fb->attrs) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_if_nok (error);
- field->type = mono_metadata_type_dup (klass->image, type);
- field->type->attrs = fb->attrs;
+ if (!info->name) {
+ if (last_point) {
+ info->name_space = start;
+ *last_point = 0;
+ info->name = last_point + 1;
} else {
- field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_if_nok (error);
- }
-
- if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
- char *base = mono_array_addr (rva_data, char, 0);
- size_t size = mono_array_length (rva_data);
- char *data = (char *)mono_image_alloc (klass->image, size);
- memcpy (data, base, size);
- klass->ext->field_def_values [i].data = data;
- }
- if (fb->offset != -1)
- field->offset = fb->offset;
- field->parent = klass;
- fb->handle = field;
- mono_save_custom_attrs (klass->image, field, fb->cattrs);
-
- if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
- }
- if (fb->def_value) {
- MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
- field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
- idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
- memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
+ info->name_space = (char *)"";
+ info->name = start;
}
}
+ while (*p) {
+ switch (*p) {
+ case '&':
+ if (isbyref) /* only one level allowed by the spec */
+ return 0;
+ isbyref = 1;
+ isptr = 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
+ *p++ = 0;
+ break;
+ case '*':
+ if (isbyref) /* pointer to ref not okay */
+ return 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
+ isptr = 1;
+ *p++ = 0;
+ break;
+ case '[':
+ if (isbyref) /* array of ref and generic ref are not okay */
+ return 0;
+ //Decide if it's an array of a generic argument list
+ *p++ = 0;
- klass->instance_size = MAX (klass->instance_size, real_size);
- mono_class_layout_fields (klass, klass->instance_size);
-}
-
-static void
-typebuilder_setup_properties (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionPropertyBuilder *pb;
- MonoImage *image = klass->image;
- MonoProperty *properties;
- int i;
+ if (!*p) //XXX test
+ return 0;
+ if (*p == ',' || *p == '*' || *p == ']') { //array
+ isptr = 0;
+ rank = 1;
+ while (*p) {
+ if (*p == ']')
+ break;
+ if (*p == ',')
+ rank++;
+ else if (*p == '*') /* '*' means unknown lower bound */
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
+ else
+ return 0;
+ ++p;
+ }
+ if (*p++ != ']')
+ return 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
+ } else {
+ if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
+ return 0;
+ isptr = 0;
+ info->type_arguments = g_ptr_array_new ();
+ while (*p) {
+ MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
+ gboolean fqname = FALSE;
- mono_error_init (error);
+ g_ptr_array_add (info->type_arguments, subinfo);
- if (!klass->ext)
- klass->ext = image_g_new0 (image, MonoClassExt, 1);
+ while (*p == ' ') p++;
+ if (*p == '[') {
+ p++;
+ fqname = TRUE;
+ }
- klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
- klass->ext->property.first = 0;
+ if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
+ return 0;
- properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
- klass->ext->properties = properties;
- for (i = 0; i < klass->ext->property.count; ++i) {
- pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
- properties [i].parent = klass;
- properties [i].attrs = pb->attrs;
- properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
- if (!mono_error_ok (error))
- return;
- if (pb->get_method)
- properties [i].get = pb->get_method->mhandle;
- if (pb->set_method)
- properties [i].set = pb->set_method->mhandle;
-
- mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
- if (pb->def_value) {
- guint32 len, idx;
- const char *p, *p2;
- MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
- if (!klass->ext->prop_def_values)
- klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
- properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
- idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
- memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
- }
- }
-}
+ /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
+ if (fqname && (*p != ']')) {
+ char *aname;
-static MonoReflectionEvent *
-reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
-{
- mono_error_init (error);
+ if (*p != ',')
+ return 0;
+ *p++ = 0;
- MonoEvent *event = g_new0 (MonoEvent, 1);
- MonoClass *klass;
+ aname = p;
+ while (*p && (*p != ']'))
+ p++;
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- if (!is_ok (error)) {
- g_free (event);
- return NULL;
- }
- klass = mono_class_from_mono_type (type);
+ if (*p != ']')
+ return 0;
- event->parent = klass;
- event->attrs = eb->attrs;
- event->name = mono_string_to_utf8_checked (eb->name, error);
- if (!is_ok (error)) {
- g_free (event);
- return NULL;
- }
- if (eb->add_method)
- event->add = eb->add_method->mhandle;
- if (eb->remove_method)
- event->remove = eb->remove_method->mhandle;
- if (eb->raise_method)
- event->raise = eb->raise_method->mhandle;
-
-#ifndef MONO_SMALL_CONFIG
- if (eb->other_methods) {
- int j;
- event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
- for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (eb->other_methods,
- MonoReflectionMethodBuilder*, j);
- event->other [j] = mb->mhandle;
+ *p++ = 0;
+ while (*aname) {
+ if (g_ascii_isspace (*aname)) {
+ ++aname;
+ continue;
+ }
+ break;
+ }
+ if (!*aname ||
+ !assembly_name_to_aname (&subinfo->assembly, aname))
+ return 0;
+ } else if (fqname && (*p == ']')) {
+ *p++ = 0;
+ }
+ if (*p == ']') {
+ *p++ = 0;
+ break;
+ } else if (!*p) {
+ return 0;
+ }
+ *p++ = 0;
+ }
+ }
+ break;
+ case ']':
+ if (is_recursed)
+ goto end;
+ return 0;
+ case ',':
+ if (is_recursed)
+ goto end;
+ *p++ = 0;
+ while (*p) {
+ if (g_ascii_isspace (*p)) {
+ ++p;
+ continue;
+ }
+ break;
+ }
+ if (!*p)
+ return 0; /* missing assembly name */
+ if (!assembly_name_to_aname (&info->assembly, p))
+ return 0;
+ break;
+ default:
+ return 0;
}
+ if (info->assembly.name)
+ break;
}
-#endif
-
- MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
- if (!is_ok (error)) {
-#ifndef MONO_SMALL_CONFIG
- g_free (event->other);
-#endif
- g_free (event);
- return NULL;
- }
- return ev_obj;
-}
-
-MonoReflectionEvent *
-ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
-{
- MonoError error;
- MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
- mono_error_set_pending_exception (&error);
- return result;
+ // *w = 0; /* terminate class name */
+ end:
+ if (!info->name || !*info->name)
+ return 0;
+ if (endptr)
+ *endptr = p;
+ /* add other consistency checks */
+ return 1;
}
-static void
-typebuilder_setup_events (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionEventBuilder *eb;
- MonoImage *image = klass->image;
- MonoEvent *events;
- int i;
-
- mono_error_init (error);
-
- if (!klass->ext)
- klass->ext = image_g_new0 (image, MonoClassExt, 1);
-
- klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
- klass->ext->event.first = 0;
- events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
- klass->ext->events = events;
- for (i = 0; i < klass->ext->event.count; ++i) {
- eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
- events [i].parent = klass;
- events [i].attrs = eb->attrs;
- events [i].name = mono_string_to_utf8_image (image, eb->name, error);
- if (!mono_error_ok (error))
- return;
- if (eb->add_method)
- events [i].add = eb->add_method->mhandle;
- if (eb->remove_method)
- events [i].remove = eb->remove_method->mhandle;
- if (eb->raise_method)
- events [i].raise = eb->raise_method->mhandle;
-
-#ifndef MONO_SMALL_CONFIG
- if (eb->other_methods) {
- int j;
- events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
- for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (eb->other_methods,
- MonoReflectionMethodBuilder*, j);
- events [i].other [j] = mb->mhandle;
- }
+/**
+ * mono_identifier_unescape_type_name_chars:
+ * @identifier: the display name of a mono type
+ *
+ * Returns:
+ * The name in internal form, that is without escaping backslashes.
+ *
+ * The string is modified in place!
+ */
+char*
+mono_identifier_unescape_type_name_chars(char* identifier)
+{
+ char *w, *r;
+ if (!identifier)
+ return NULL;
+ for (w = r = identifier; *r != 0; r++)
+ {
+ char c = *r;
+ if (c == '\\') {
+ r++;
+ if (*r == 0)
+ break;
+ c = *r;
}
-#endif
- mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
+ *w = c;
+ w++;
}
+ if (w != r)
+ *w = 0;
+ return identifier;
}
-struct remove_instantiations_user_data
-{
- MonoClass *klass;
- MonoError *error;
-};
+void
+mono_identifier_unescape_info (MonoTypeNameParse* info);
-static gboolean
-remove_instantiations_of_and_ensure_contents (gpointer key,
- gpointer value,
- gpointer user_data)
+static void
+unescape_each_type_argument(void* data, void* user_data)
{
- struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
- MonoType *type = (MonoType*)key;
- MonoClass *klass = data->klass;
- gboolean already_failed = !is_ok (data->error);
- MonoError lerror;
- MonoError *error = already_failed ? &lerror : data->error;
-
- if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
- MonoClass *inst_klass = mono_class_from_mono_type (type);
- //Ensure it's safe to use it.
- if (!fix_partial_generic_class (inst_klass, error)) {
- mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- // Marked the class with failure, but since some other instantiation already failed,
- // just report that one, and swallow the error from this one.
- if (already_failed)
- mono_error_cleanup (error);
- }
- return TRUE;
- } else
- return FALSE;
+ MonoTypeNameParse* info = (MonoTypeNameParse*)data;
+ mono_identifier_unescape_info (info);
}
static void
-check_array_for_usertypes (MonoArray *arr, MonoError *error)
+unescape_each_nested_name (void* data, void* user_data)
{
- mono_error_init (error);
- int i;
+ char* nested_name = (char*) data;
+ mono_identifier_unescape_type_name_chars(nested_name);
+}
- if (!arr)
+/**
+ * mono_identifier_unescape_info:
+ *
+ * @info: a parsed display form of an (optionally assembly qualified) full type name.
+ *
+ * Returns: nothing.
+ *
+ * Destructively updates the info by unescaping the identifiers that
+ * comprise the type namespace, name, nested types (if any) and
+ * generic type arguments (if any).
+ *
+ * The resulting info has the names in internal form.
+ *
+ */
+void
+mono_identifier_unescape_info (MonoTypeNameParse *info)
+{
+ if (!info)
return;
+ mono_identifier_unescape_type_name_chars(info->name_space);
+ mono_identifier_unescape_type_name_chars(info->name);
+ // but don't escape info->assembly
+ if (info->type_arguments)
+ g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
+ if (info->nested)
+ g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
+}
- for (i = 0; i < mono_array_length (arr); ++i) {
- RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
- if (!mono_error_ok (error))
- break;
+int
+mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
+{
+ int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
+ if (ok) {
+ mono_identifier_unescape_info (info);
}
+ return ok;
}
-MonoReflectionType*
-ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
+static MonoType*
+_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
{
- MonoError error;
- MonoClass *klass;
- MonoDomain* domain;
- MonoReflectionType* res;
- int i, j;
-
- mono_error_init (&error);
+ gboolean type_resolve = FALSE;
+ MonoType *type;
+ MonoImage *rootimage = image;
- domain = mono_object_domain (tb);
- klass = mono_class_from_mono_type (tb->type.type);
+ mono_error_init (error);
- /*
- * Check for user defined Type subclasses.
- */
- RESOLVE_TYPE (tb->parent, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (tb->interfaces, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (tb->fields) {
- for (i = 0; i < mono_array_length (tb->fields); ++i) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
- if (fb) {
- RESOLVE_TYPE (fb->type, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (fb->modreq, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (fb->modopt, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
- RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
- }
- }
- if (tb->methods) {
- for (i = 0; i < mono_array_length (tb->methods); ++i) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
- if (mb) {
- RESOLVE_TYPE (mb->rtype, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->return_modreq, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->return_modopt, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->parameters, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (mb->param_modreq)
- for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- if (mb->param_modopt)
- for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
- }
- }
- if (tb->ctors) {
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
- if (mb) {
- check_array_for_usertypes (mb->parameters, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (mb->param_modreq)
- for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- if (mb->param_modopt)
- for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
+ if (info->assembly.name) {
+ MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
+ if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
+ /*
+ * This could happen in the AOT compiler case when the search hook is not
+ * installed.
+ */
+ assembly = image->assembly;
+ if (!assembly) {
+ /* then we must load the assembly ourselve - see #60439 */
+ assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
+ if (!assembly)
+ return NULL;
}
+ image = assembly->image;
+ } else if (!image) {
+ image = mono_defaults.corlib;
}
- mono_save_custom_attrs (klass->image, klass, tb->cattrs);
-
- /*
- * we need to lock the domain because the lock will be taken inside
- * So, we need to keep the locking order correct.
- */
- mono_loader_lock ();
- mono_domain_lock (domain);
- if (klass->wastypebuilder) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return res;
+ type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
+ if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
+ /* ignore the error and try again */
+ mono_error_cleanup (error);
+ mono_error_init (error);
+ image = mono_defaults.corlib;
+ type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
}
- /*
- * Fields to set in klass:
- * the various flags: delegate/unicode/contextbound etc.
- */
- klass->flags = tb->attrs;
- klass->has_cctor = 1;
-
- mono_class_setup_parent (klass, klass->parent);
- /* fool mono_class_setup_supertypes */
- klass->supertypes = NULL;
- mono_class_setup_supertypes (klass);
- mono_class_setup_mono_type (klass);
-
-#if 0
- if (!((MonoDynamicImage*)klass->image)->run) {
- if (klass->generic_container) {
- /* FIXME: The code below can't handle generic classes */
- klass->wastypebuilder = TRUE;
- mono_loader_unlock ();
- mono_domain_unlock (domain);
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return res;
- }
- }
-#endif
+ return type;
+}
- /* enums are done right away */
- if (!klass->enumtype)
- if (!ensure_runtime_vtable (klass, &error))
- goto failure;
+/**
+ * mono_reflection_get_type_internal:
+ *
+ * Returns: may return NULL on success, sets error on failure.
+ */
+static MonoType*
+mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
+{
+ MonoClass *klass;
+ GList *mod;
+ int modval;
+ gboolean bounded = FALSE;
+
+ mono_error_init (error);
+ if (!image)
+ image = mono_defaults.corlib;
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
- mono_class_alloc_ext (klass);
- MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
- if (!is_ok (&error)) goto failure;
- klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
- }
- }
+ if (!rootimage)
+ rootimage = mono_defaults.corlib;
- klass->nested_classes_inited = TRUE;
-
- /* fields and object layout */
- if (klass->parent) {
- if (!klass->parent->size_inited)
- mono_class_init (klass->parent);
- klass->instance_size = klass->parent->instance_size;
- klass->sizes.class_size = 0;
- klass->min_align = klass->parent->min_align;
- /* if the type has no fields we won't call the field_setup
- * routine which sets up klass->has_references.
- */
- klass->has_references |= klass->parent->has_references;
- } else {
- klass->instance_size = sizeof (MonoObject);
- klass->min_align = 1;
- }
+ if (ignorecase)
+ klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
+ else
+ klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
- /* FIXME: handle packing_size and instance_size */
- typebuilder_setup_fields (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
- typebuilder_setup_properties (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
+ if (!klass)
+ return NULL;
- typebuilder_setup_events (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
+ for (mod = info->nested; mod; mod = mod->next) {
+ gpointer iter = NULL;
+ MonoClass *parent;
- klass->wastypebuilder = TRUE;
+ parent = klass;
+ mono_class_init (parent);
- /*
- * If we are a generic TypeBuilder, there might be instantiations in the type cache
- * which have type System.Reflection.MonoGenericClass, but after the type is created,
- * we want to return normal System.MonoType objects, so clear these out from the cache.
- *
- * Together with this we must ensure the contents of all instances to match the created type.
- */
- if (domain->type_hash && klass->generic_container) {
- struct remove_instantiations_user_data data;
- data.klass = klass;
- data.error = &error;
- mono_error_assert_ok (&error);
- mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
- if (!is_ok (&error))
- goto failure;
- }
+ while ((klass = mono_class_get_nested_types (parent, &iter))) {
+ char *lastp;
+ char *nested_name, *nested_nspace;
+ gboolean match = TRUE;
- mono_domain_unlock (domain);
- mono_loader_unlock ();
+ lastp = strrchr ((const char *)mod->data, '.');
+ if (lastp) {
+ /* Nested classes can have namespaces */
+ int nspace_len;
- if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
- goto failure_unlocked;
- }
+ nested_name = g_strdup (lastp + 1);
+ nspace_len = lastp - (char*)mod->data;
+ nested_nspace = (char *)g_malloc (nspace_len + 1);
+ memcpy (nested_nspace, mod->data, nspace_len);
+ nested_nspace [nspace_len] = '\0';
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
+ } else {
+ nested_name = (char *)mod->data;
+ nested_nspace = NULL;
+ }
- g_assert (res != (MonoReflectionType*)tb);
+ if (nested_nspace) {
+ if (ignorecase) {
+ if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
+ match = FALSE;
+ } else {
+ if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
+ match = FALSE;
+ }
+ }
+ if (match) {
+ if (ignorecase) {
+ if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
+ match = FALSE;
+ } else {
+ if (strcmp (klass->name, nested_name) != 0)
+ match = FALSE;
+ }
+ }
+ if (lastp) {
+ g_free (nested_name);
+ g_free (nested_nspace);
+ }
+ if (match)
+ break;
+ }
- return res;
+ if (!klass)
+ break;
+ }
+ if (!klass)
+ return NULL;
-failure:
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- klass->wastypebuilder = TRUE;
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-failure_unlocked:
- mono_error_set_pending_exception (&error);
- return NULL;
-}
+ if (info->type_arguments) {
+ MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
+ MonoReflectionType *the_type;
+ MonoType *instance;
+ int i;
-static gboolean
-reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
-{
- MonoGenericParamFull *param;
- MonoImage *image;
- MonoClass *pklass;
+ for (i = 0; i < info->type_arguments->len; i++) {
+ MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
- mono_error_init (error);
+ type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
+ if (!type_args [i]) {
+ g_free (type_args);
+ return NULL;
+ }
+ }
- image = &gparam->tbuilder->module->dynamic_image->image;
+ the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
+ if (!the_type)
+ return NULL;
- param = mono_image_new0 (image, MonoGenericParamFull, 1);
+ instance = mono_reflection_bind_generic_parameters (
+ the_type, info->type_arguments->len, type_args, error);
- param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
- mono_error_assert_ok (error);
- param->param.num = gparam->index;
+ g_free (type_args);
+ if (!instance)
+ return NULL;
- if (gparam->mbuilder) {
- if (!gparam->mbuilder->generic_container) {
- MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
- return_val_if_nok (error, FALSE);
+ klass = mono_class_from_mono_type (instance);
+ }
- MonoClass *klass = mono_class_from_mono_type (tb);
- gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
- gparam->mbuilder->generic_container->is_method = TRUE;
- /*
- * Cannot set owner.method, since the MonoMethod is not created yet.
- * Set the image field instead, so type_in_image () works.
- */
- gparam->mbuilder->generic_container->is_anonymous = TRUE;
- gparam->mbuilder->generic_container->owner.image = klass->image;
- }
- param->param.owner = gparam->mbuilder->generic_container;
- } else if (gparam->tbuilder) {
- if (!gparam->tbuilder->generic_container) {
- MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
- return_val_if_nok (error, FALSE);
- MonoClass *klass = mono_class_from_mono_type (tb);
- gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
- gparam->tbuilder->generic_container->owner.klass = klass;
+ for (mod = info->modifiers; mod; mod = mod->next) {
+ modval = GPOINTER_TO_UINT (mod->data);
+ if (!modval) { /* byref: must be last modifier */
+ return &klass->this_arg;
+ } else if (modval == -1) {
+ klass = mono_ptr_class_get (&klass->byval_arg);
+ } else if (modval == -2) {
+ bounded = TRUE;
+ } else { /* array rank */
+ klass = mono_bounded_array_class_get (klass, modval, bounded);
}
- param->param.owner = gparam->tbuilder->generic_container;
}
- pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
-
- gparam->type.type = &pklass->byval_arg;
+ return &klass->byval_arg;
+}
- mono_class_set_ref_info (pklass, gparam);
- mono_image_append_class_to_reflection_info_set (pklass);
+/*
+ * mono_reflection_get_type:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ *
+ * Build a MonoType from the type description in @info.
+ *
+ */
- return TRUE;
+MonoType*
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
+ MonoError error;
+ MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-void
-ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
-{
- MonoError error;
- (void) reflection_initialize_generic_parameter (gparam, &error);
- mono_error_set_pending_exception (&error);
+/**
+ * mono_reflection_get_type_checked:
+ * @rootimage: the image of the currently active managed caller
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ * @error: set on error.
+ *
+ * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
+ *
+ */
+MonoType*
+mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
+ mono_error_init (error);
+ return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
}
-static MonoArray *
-reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
+static MonoType*
+mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
{
- MonoReflectionModuleBuilder *module = sig->module;
- MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
- guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
- guint32 buflen, i;
- MonoArray *result;
- SigBuffer buf;
+ MonoReflectionAssemblyBuilder *abuilder;
+ MonoType *type;
+ int i;
mono_error_init (error);
+ g_assert (assembly_is_dynamic (assembly));
+ abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
+ if (!abuilder)
+ return NULL;
- check_array_for_usertypes (sig->arguments, error);
- return_val_if_nok (error, NULL);
-
- sigbuffer_init (&buf, 32);
+ /* Enumerate all modules */
- sigbuffer_add_value (&buf, 0x07);
- sigbuffer_add_value (&buf, na);
- if (assembly != NULL){
- for (i = 0; i < na; ++i) {
- MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, type, &buf, error);
- if (!is_ok (error)) goto fail;
+ type = NULL;
+ if (abuilder->modules) {
+ for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
+ MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
+ type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
+ if (type)
+ break;
+ if (!mono_error_ok (error))
+ return NULL;
}
}
- buflen = buf.p - buf.buf;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error)) goto fail;
- memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
- sigbuffer_free (&buf);
- return result;
-fail:
- sigbuffer_free (&buf);
- return NULL;
-}
+ if (!type && abuilder->loaded_modules) {
+ for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
+ MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
+ type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
+ if (type)
+ break;
+ if (!mono_error_ok (error))
+ return NULL;
+ }
+ }
-MonoArray *
-ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
-{
- MonoError error;
- MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
- mono_error_set_pending_exception (&error);
- return result;
+ return type;
}
-
-static MonoArray *
-reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
+
+MonoType*
+mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
{
- MonoDynamicImage *assembly = sig->module->dynamic_image;
- guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
- guint32 buflen, i;
- MonoArray *result;
- SigBuffer buf;
+ MonoType *type;
+ MonoReflectionAssembly *assembly;
+ GString *fullName;
+ GList *mod;
mono_error_init (error);
- check_array_for_usertypes (sig->arguments, error);
+ if (image && image_is_dynamic (image))
+ type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
+ else {
+ type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
+ }
return_val_if_nok (error, NULL);
- sigbuffer_init (&buf, 32);
+ if (type)
+ return type;
+ if (!mono_domain_has_type_resolve (mono_domain_get ()))
+ return NULL;
- sigbuffer_add_value (&buf, 0x06);
- for (i = 0; i < na; ++i) {
- MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, type, &buf, error);
- if (!is_ok (error))
- goto fail;
+ if (type_resolve) {
+ if (*type_resolve)
+ return NULL;
+ else
+ *type_resolve = TRUE;
}
+
+ /* Reconstruct the type name */
+ fullName = g_string_new ("");
+ if (info->name_space && (info->name_space [0] != '\0'))
+ g_string_printf (fullName, "%s.%s", info->name_space, info->name);
+ else
+ g_string_printf (fullName, "%s", info->name);
+ for (mod = info->nested; mod; mod = mod->next)
+ g_string_append_printf (fullName, "+%s", (char*)mod->data);
- buflen = buf.p - buf.buf;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error)) goto fail;
- memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
- sigbuffer_free (&buf);
-
- return result;
-fail:
- sigbuffer_free (&buf);
- return NULL;
-}
-
-MonoArray *
-ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
-{
- MonoError error;
- MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-typedef struct {
- MonoMethod *handle;
- MonoDomain *domain;
-} DynamicMethodReleaseData;
-
-/*
- * The runtime automatically clean up those after finalization.
-*/
-static MonoReferenceQueue *dynamic_method_queue;
-
-static void
-free_dynamic_method (void *dynamic_method)
-{
- DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
- MonoDomain *domain = data->domain;
- MonoMethod *method = data->handle;
- guint32 dis_link;
-
- mono_domain_lock (domain);
- dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
- g_hash_table_remove (domain->method_to_dyn_method, method);
- mono_domain_unlock (domain);
- g_assert (dis_link);
- mono_gchandle_free (dis_link);
-
- mono_runtime_free_method (domain, method);
- g_free (data);
-}
-
-static gboolean
-reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
-{
- MonoReferenceQueue *queue;
- MonoMethod *handle;
- DynamicMethodReleaseData *release_data;
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
- MonoClass *klass;
- MonoDomain *domain;
- GSList *l;
- int i;
-
- mono_error_init (error);
-
- if (mono_runtime_is_shutting_down ()) {
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
- return FALSE;
+ assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
+ if (!is_ok (error)) {
+ g_string_free (fullName, TRUE);
+ return NULL;
}
- if (!(queue = dynamic_method_queue)) {
- mono_loader_lock ();
- if (!(queue = dynamic_method_queue))
- queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
- mono_loader_unlock ();
+ if (assembly) {
+ if (assembly_is_dynamic (assembly->assembly))
+ type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
+ info, ignorecase, error);
+ else
+ type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
+ info, ignorecase, error);
}
+ g_string_free (fullName, TRUE);
+ return_val_if_nok (error, NULL);
+ return type;
+}
- sig = dynamic_method_to_signature (mb, error);
- return_val_if_nok (error, FALSE);
-
- reflection_methodbuilder_from_dynamic_method (&rmb, mb);
-
- /*
- * Resolve references.
- */
- /*
- * Every second entry in the refs array is reserved for storing handle_class,
- * which is needed by the ldtoken implementation in the JIT.
- */
- rmb.nrefs = mb->nrefs;
- rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
- for (i = 0; i < mb->nrefs; i += 2) {
- MonoClass *handle_class;
- gpointer ref;
- MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
-
- if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
- /*
- * The referenced DynamicMethod should already be created by the managed
- * code, except in the case of circular references. In that case, we store
- * method in the refs array, and fix it up later when the referenced
- * DynamicMethod is created.
- */
- if (method->mhandle) {
- ref = method->mhandle;
- } else {
- /* FIXME: GC object stored in unmanaged memory */
- ref = method;
+void
+mono_reflection_free_type_info (MonoTypeNameParse *info)
+{
+ g_list_free (info->modifiers);
+ g_list_free (info->nested);
- /* FIXME: GC object stored in unmanaged memory */
- method->referenced_by = g_slist_append (method->referenced_by, mb);
- }
- handle_class = mono_defaults.methodhandle_class;
- } else {
- MonoException *ex = NULL;
- ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
- if (!is_ok (error)) {
- g_free (rmb.refs);
- return FALSE;
- }
- if (!ref)
- ex = mono_get_exception_type_load (NULL, NULL);
- else if (mono_security_core_clr_enabled ())
- ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
-
- if (ex) {
- g_free (rmb.refs);
- mono_error_set_exception_instance (error, ex);
- return FALSE;
- }
- }
+ if (info->type_arguments) {
+ int i;
- rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
- rmb.refs [i + 1] = handle_class;
- }
+ for (i = 0; i < info->type_arguments->len; i++) {
+ MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
- if (mb->owner) {
- MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
- if (!is_ok (error)) {
- g_free (rmb.refs);
- return FALSE;
+ mono_reflection_free_type_info (subinfo);
+ /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
+ g_free (subinfo);
}
- klass = mono_class_from_mono_type (owner_type);
- } else {
- klass = mono_defaults.object_class;
- }
-
- mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- g_free (rmb.refs);
- return_val_if_nok (error, FALSE);
-
- release_data = g_new (DynamicMethodReleaseData, 1);
- release_data->handle = handle;
- release_data->domain = mono_object_get_domain ((MonoObject*)mb);
- if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
- g_free (release_data);
-
- /* Fix up refs entries pointing at us */
- for (l = mb->referenced_by; l; l = l->next) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
- MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
- gpointer *data;
-
- g_assert (method->mhandle);
- data = (gpointer*)wrapper->method_data;
- for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
- if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
- data [i + 1] = mb->mhandle;
- }
+ g_ptr_array_free (info->type_arguments, TRUE);
}
- g_slist_free (mb->referenced_by);
-
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
-
- domain = mono_domain_get ();
- mono_domain_lock (domain);
- if (!domain->method_to_dyn_method)
- domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
- mono_domain_unlock (domain);
-
- return TRUE;
}
-void
-ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
-{
- MonoError error;
- (void) reflection_create_dynamic_method (mb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-#endif /* DISABLE_REFLECTION_EMIT */
-
-/**
- *
- * mono_reflection_is_valid_dynamic_token:
- *
- * Returns TRUE if token is valid.
+/*
+ * mono_reflection_type_from_name:
+ * @name: type name.
+ * @image: a metadata context (can be NULL).
+ *
+ * Retrieves a MonoType from its @name. If the name is not fully qualified,
+ * it defaults to get the type from @image or, if @image is NULL or loading
+ * from it fails, uses corlib.
*
*/
-gboolean
-mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
-{
- return lookup_dyn_token (image, token) != NULL;
-}
-
-MonoMethodSignature *
-mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
+MonoType*
+mono_reflection_type_from_name (char *name, MonoImage *image)
{
- MonoMethodSignature *sig;
- g_assert (image_is_dynamic (image));
-
- mono_error_init (error);
-
- sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
- if (sig)
- return sig;
-
- return mono_method_signature_checked (method, error);
+ MonoError error;
+ MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-#ifndef DISABLE_REFLECTION_EMIT
-
/**
- * mono_reflection_lookup_dynamic_token:
- *
- * Finish the Builder object pointed to by TOKEN and return the corresponding
- * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
- * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
- * mapping table.
+ * mono_reflection_type_from_name_checked:
+ * @name: type name.
+ * @image: a metadata context (can be NULL).
+ * @error: set on errror.
*
- * LOCKING: Take the loader lock
+ * Retrieves a MonoType from its @name. If the name is not fully qualified,
+ * it defaults to get the type from @image or, if @image is NULL or loading
+ * from it fails, uses corlib. On failure returns NULL and sets @error.
+ *
*/
-gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+MonoType*
+mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
{
- MonoDynamicImage *assembly = (MonoDynamicImage*)image;
- MonoObject *obj;
- MonoClass *klass;
+ MonoType *type = NULL;
+ MonoTypeNameParse info;
+ char *tmp;
mono_error_init (error);
+ /* Make a copy since parse_type modifies its argument */
+ tmp = g_strdup (name);
- obj = lookup_dyn_token (assembly, token);
- if (!obj) {
- if (valid_token)
- g_error ("Could not find required dynamic token 0x%08x", token);
- else {
- mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
+ /*g_print ("requested type %s\n", str);*/
+ if (mono_reflection_parse_type (tmp, &info)) {
+ type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
+ if (!is_ok (error)) {
+ g_free (tmp);
+ mono_reflection_free_type_info (&info);
return NULL;
}
}
- if (!handle_class)
- handle_class = &klass;
- gpointer result = resolve_object (image, obj, handle_class, context, error);
- return result;
+ g_free (tmp);
+ mono_reflection_free_type_info (&info);
+ return type;
}
/*
- * ensure_complete_type:
+ * mono_reflection_get_token:
*
- * Ensure that KLASS is completed if it is a dynamic type, or references
- * dynamic types.
+ * Return the metadata token of OBJ which should be an object
+ * representing a metadata element.
*/
-static void
-ensure_complete_type (MonoClass *klass, MonoError *error)
+guint32
+mono_reflection_get_token (MonoObject *obj)
{
- mono_error_init (error);
-
- if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ MonoError error;
+ guint32 result = mono_reflection_get_token_checked (obj, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_if_nok (error);
+/**
+ * mono_reflection_get_token_checked:
+ * @obj: the object
+ * @error: set on error
+ *
+ * Return the metadata token of @obj which should be an object
+ * representing a metadata element. On failure sets @error.
+ */
+guint32
+mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
+{
+ MonoClass *klass;
+ guint32 token = 0;
- // Asserting here could break a lot of code
- //g_assert (klass->wastypebuilder);
- }
+ mono_error_init (error);
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
- int i;
+ klass = obj->vtable->klass;
- for (i = 0; i < inst->type_argc; ++i) {
- ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
- return_if_nok (error);
- }
- }
-}
+ if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
-static gpointer
-resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
-{
- gpointer result = NULL;
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
- mono_error_init (error);
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
- if (strcmp (obj->vtable->klass->name, "String") == 0) {
- result = mono_string_intern_checked ((MonoString*)obj, error);
- return_val_if_nok (error, NULL);
- *handle_class = mono_defaults.string_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
+ token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+ } else if (strcmp (klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ } else if (strcmp (klass->name, "RuntimeType") == 0) {
MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
+ return_val_if_nok (error, 0);
MonoClass *mc = mono_class_from_mono_type (type);
if (!mono_class_init (mc)) {
mono_error_set_for_class_failure (error, mc);
- return NULL;
+ return 0;
}
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (inflated);
- mono_metadata_free_type (inflated);
+ token = mc->type_token;
+ } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ strcmp (klass->name, "MonoMethod") == 0 ||
+ strcmp (klass->name, "MonoGenericMethod") == 0 ||
+ strcmp (klass->name, "MonoGenericCMethod") == 0) {
+ MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
+ if (m->method->is_inflated) {
+ MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
+ return inflated->declaring->token;
} else {
- result = mono_class_from_mono_type (type);
- }
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
- result = ((MonoReflectionMethod*)obj)->method;
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- *handle_class = mono_defaults.methodhandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
- result = mb->mhandle;
- if (!result) {
- /* Type is not yet created */
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
-
- /*
- * Hopefully this has been filled in by calling CreateType() on the
- * TypeBuilder.
- */
- /*
- * TODO: This won't work if the application finishes another
- * TypeBuilder instance instead of this one.
- */
- result = mb->mhandle;
- }
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
+ token = m->method->token;
}
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
+ } else if (strcmp (klass->name, "MonoField") == 0) {
+ MonoReflectionField *f = (MonoReflectionField*)obj;
- result = cb->mhandle;
- if (!result) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
+ token = mono_class_get_field_token (f->field);
+ } else if (strcmp (klass->name, "MonoProperty") == 0) {
+ MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = cb->mhandle;
- }
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
- MonoClassField *field = ((MonoReflectionField*)obj)->field;
+ token = mono_class_get_property_token (p->property);
+ } else if (strcmp (klass->name, "MonoEvent") == 0) {
+ MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
- ensure_complete_type (field->parent, error);
- return_val_if_nok (error, NULL);
+ token = mono_class_get_event_token (p->event);
+ } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
+ MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
+ MonoClass *member_class = mono_object_class (p->MemberImpl);
+ g_assert (mono_class_is_reflection_method_or_constructor (member_class));
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *klass = mono_class_from_mono_type (inflated);
- MonoClassField *inflated_field;
- gpointer iter = NULL;
- mono_metadata_free_type (inflated);
- while ((inflated_field = mono_class_get_fields (klass, &iter))) {
- if (!strcmp (field->name, inflated_field->name))
- break;
- }
- g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
- result = inflated_field;
- } else {
- result = field;
- }
- *handle_class = mono_defaults.fieldhandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
- result = fb->handle;
+ token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
+ } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
+ MonoReflectionModule *m = (MonoReflectionModule*)obj;
- if (!result) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
+ token = m->token;
+ } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
+ token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
+ } else {
+ mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
+ klass->name_space, klass->name);
+ return 0;
+ }
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = fb->handle;
- }
+ return token;
+}
- if (fb->handle && fb->handle->parent->generic_container) {
- MonoClass *klass = fb->handle->parent;
- MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
- return_val_if_nok (error, NULL);
- MonoClass *inflated = mono_class_from_mono_type (type);
+gboolean
+mono_reflection_is_usertype (MonoReflectionType *ref)
+{
+ MonoClass *klass = mono_object_class (ref);
+ return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
+}
- result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
- g_assert (result);
- mono_metadata_free_type (type);
- }
- *handle_class = mono_defaults.fieldhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, NULL);
- MonoClass *klass;
+/**
+ * mono_reflection_bind_generic_parameters:
+ * @type: a managed type object (which should be some kind of generic (instance? definition?))
+ * @type_args: the number of type arguments to bind
+ * @types: array of type arguments
+ * @error: set on error
+ *
+ * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
+ * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
+ */
+MonoType*
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
+{
+ MonoClass *klass;
+ MonoReflectionTypeBuilder *tb = NULL;
+ gboolean is_dynamic = FALSE;
+ MonoClass *geninst;
- klass = type->data.klass;
- if (klass->wastypebuilder) {
- /* Already created */
- result = klass;
- }
- else {
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = type->data.klass;
- g_assert (result);
- }
- *handle_class = mono_defaults.typehandle_class;
- } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
- MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
- MonoMethodSignature *sig;
- int nargs, i;
-
- if (helper->arguments)
- nargs = mono_array_length (helper->arguments);
- else
- nargs = 0;
+ mono_error_init (error);
+
+ mono_loader_lock ();
- sig = mono_metadata_signature_alloc (image, nargs);
- sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
- sig->hasthis = helper->call_conv & 32 ? 1 : 0;
+ if (mono_is_sre_type_builder (mono_object_class (type))) {
+ tb = (MonoReflectionTypeBuilder *) type;
- if (helper->unmanaged_call_conv) { /* unmanaged */
- sig->call_convention = helper->unmanaged_call_conv - 1;
- sig->pinvoke = TRUE;
- } else if (helper->call_conv & 0x02) {
- sig->call_convention = MONO_CALL_VARARG;
- } else {
- sig->call_convention = MONO_CALL_DEFAULT;
- }
+ is_dynamic = TRUE;
+ } else if (mono_is_sre_generic_instance (mono_object_class (type))) {
+ MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
+ MonoReflectionType *gtd = rgi->generic_type;
- sig->param_count = nargs;
- /* TODO: Copy type ? */
- sig->ret = helper->return_type->type;
- for (i = 0; i < nargs; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
+ if (mono_is_sre_type_builder (mono_object_class (gtd))) {
+ tb = (MonoReflectionTypeBuilder *)gtd;
+ is_dynamic = TRUE;
}
+ }
- result = sig;
- *handle_class = NULL;
- } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
- /* Already created by the managed code */
- g_assert (method->mhandle);
- result = method->mhandle;
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (type);
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (type);
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
- MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
- MonoClass *inflated;
- MonoType *type;
- MonoClassField *field;
-
- if (is_sre_field_builder (mono_object_class (f->fb)))
- field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
- else if (is_sr_mono_field (mono_object_class (f->fb)))
- field = ((MonoReflectionField*)f->fb)->field;
- else
- g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
-
- MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (finst, context, error);
- return_val_if_nok (error, NULL);
-
- inflated = mono_class_from_mono_type (type);
-
- result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
- ensure_complete_type (field->parent, error);
- if (!is_ok (error)) {
- mono_metadata_free_type (type);
+ /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
+ if (tb && tb->generic_container) {
+ if (!mono_reflection_create_generic_class (tb, error)) {
+ mono_loader_unlock ();
return NULL;
}
-
- g_assert (result);
- mono_metadata_free_type (type);
- *handle_class = mono_defaults.fieldhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
- MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, NULL);
- MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *method;
-
- if (is_sre_ctor_builder (mono_object_class (c->cb)))
- method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
- else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
- method = ((MonoReflectionMethod *)c->cb)->method;
- else
- g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
-
- result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
- *handle_class = mono_defaults.methodhandle_class;
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
- if (m->method_args) {
- result = mono_reflection_method_on_tb_inst_get_handle (m, error);
- return_val_if_nok (error, NULL);
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- } else {
- MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, NULL);
- MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *method;
-
- if (is_sre_method_builder (mono_object_class (m->mb)))
- method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
- else if (is_sr_mono_method (mono_object_class (m->mb)))
- method = ((MonoReflectionMethod *)m->mb)->method;
- else
- g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
-
- result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
- mono_metadata_free_type (type);
- }
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
- MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
- MonoType *mtype;
- MonoClass *klass;
- MonoMethod *method;
- gpointer iter;
- char *name;
-
- mtype = mono_reflection_type_get_handle (m->parent, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (mtype);
-
- /* Find the method */
-
- name = mono_string_to_utf8_checked (m->name, error);
- return_val_if_nok (error, NULL);
- iter = NULL;
- while ((method = mono_class_get_methods (klass, &iter))) {
- if (!strcmp (method->name, name))
- break;
- }
- g_free (name);
-
- // FIXME:
- g_assert (method);
- // FIXME: Check parameters/return value etc. match
-
- result = method;
- *handle_class = mono_defaults.methodhandle_class;
- } else if (is_sre_array (mono_object_get_class(obj)) ||
- is_sre_byref (mono_object_get_class(obj)) ||
- is_sre_pointer (mono_object_get_class(obj))) {
- MonoReflectionType *ref_type = (MonoReflectionType *)obj;
- MonoType *type = mono_reflection_type_get_handle (ref_type, error);
- return_val_if_nok (error, NULL);
-
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (inflated);
- mono_metadata_free_type (inflated);
- } else {
- result = mono_class_from_mono_type (type);
- }
- *handle_class = mono_defaults.typehandle_class;
- } else {
- g_print ("%s\n", obj->vtable->klass->name);
- g_assert_not_reached ();
}
- return result;
-}
-
-#else /* DISABLE_REFLECTION_EMIT */
-
-MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
-{
- g_assert_not_reached ();
- return NULL;
-}
-void
-ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
-}
+ MonoType *t = mono_reflection_type_get_handle (type, error);
+ if (!is_ok (error)) {
+ mono_loader_unlock ();
+ return NULL;
+ }
-void
-ves_icall_TypeBuilder_setup_generic_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
-}
+ klass = mono_class_from_mono_type (t);
+ if (!klass->generic_container) {
+ mono_loader_unlock ();
+ mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
+ return NULL;
+ }
-static gboolean
-mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- g_assert_not_reached ();
- return FALSE;
-}
+ if (klass->wastypebuilder) {
+ tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
-void
-ves_icall_TypeBuilder_create_internal_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
-}
+ is_dynamic = TRUE;
+ }
-static void
-mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
-{
- g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
-}
+ mono_loader_unlock ();
-static void
-mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
-{
- g_assert_not_reached ();
-}
+ geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
-MonoReflectionModule *
-mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
-{
- g_assert_not_reached ();
- return NULL;
+ return &geninst->byval_arg;
}
-guint32
-mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
+MonoClass*
+mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
{
- g_assert_not_reached ();
- return 0;
-}
+ MonoGenericClass *gclass;
+ MonoGenericInst *inst;
-guint32
-mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
-{
- g_assert_not_reached ();
- return 0;
-}
+ g_assert (klass->generic_container);
-guint32
-mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
- gboolean create_open_instance, gboolean register_token, MonoError *error)
-{
- g_assert_not_reached ();
- return 0;
-}
+ inst = mono_metadata_get_generic_inst (type_argc, types);
+ gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
-void
-mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
-{
+ return mono_generic_class_get_class (gclass);
}
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+static MonoReflectionMethod*
+reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
{
- g_assert_not_reached ();
-}
+ MonoClass *klass;
+ MonoMethod *method, *inflated;
+ MonoMethodInflated *imethod;
+ MonoGenericContext tmp_context;
+ MonoGenericInst *ginst;
+ MonoType **type_argv;
+ int count, i;
-void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
-{
mono_error_init (error);
- *overrides = NULL;
- *num_overrides = 0;
-}
-MonoReflectionEvent *
-ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ /*FIXME but this no longer should happen*/
+ if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
+ method = mono_reflection_method_builder_to_mono_method ((MonoReflectionMethodBuilder*)rmethod, error);
+ return_val_if_nok (error, NULL);
+ } else {
+ method = rmethod->method;
+ }
-MonoReflectionType*
-ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ klass = method->klass;
-void
-ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
-{
- g_assert_not_reached ();
-}
+ if (method->is_inflated)
+ method = ((MonoMethodInflated *) method)->declaring;
-MonoArray *
-ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ count = mono_method_signature (method)->generic_param_count;
+ if (count != mono_array_length (types))
+ return NULL;
-MonoArray *
-ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ type_argv = g_new0 (MonoType *, count);
+ for (i = 0; i < count; i++) {
+ MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
+ type_argv [i] = mono_reflection_type_get_handle (garg, error);
+ if (!is_ok (error)) {
+ g_free (type_argv);
+ return NULL;
+ }
+ }
+ ginst = mono_metadata_get_generic_inst (count, type_argv);
+ g_free (type_argv);
-void
-ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
-{
-}
+ tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ tmp_context.method_inst = ginst;
-gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
-{
- mono_error_init (error);
- return NULL;
+ inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
+ mono_error_assert_ok (error);
+ imethod = (MonoMethodInflated *) inflated;
+
+ /*FIXME but I think this is no longer necessary*/
+ if (image_is_dynamic (method->klass->image)) {
+ MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
+ /*
+ * This table maps metadata structures representing inflated methods/fields
+ * to the reflection objects representing their generic definitions.
+ */
+ mono_image_lock ((MonoImage*)image);
+ mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
+ mono_image_unlock ((MonoImage*)image);
+ }
+
+ if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
+ mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
+ return NULL;
+ }
+
+ MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
+ return ret;
}
-MonoType*
-mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
+MonoReflectionMethod*
+ves_icall_MethodBuilder_MakeGenericMethod (MonoReflectionMethod *rmethod, MonoArray *types)
{
- mono_error_init (error);
- if (!ref)
- return NULL;
- return ref->type;
+ MonoError error;
+ MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
-void
-mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
+MonoReflectionMethod*
+ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
{
- g_assert_not_reached ();
+ MonoError error;
+ MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
-#endif /* DISABLE_REFLECTION_EMIT */
/* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
const static guint32 declsec_flags_map[] = {
return refassembly->assembly;
}
-gint32
-ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
-{
- MONO_CHECK_ARG_NULL (obj, 0);
-
- MonoError error;
- gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-gint32
-ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
- MonoReflectionMethod *method,
- MonoArray *opt_param_types)
-{
- MONO_CHECK_ARG_NULL (method, 0);
-
- MonoError error;
- gint32 result = mono_image_create_method_token (
- mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-void
-ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
-{
- MonoError error;
- mono_image_create_pefile (mb, file, &error);
- mono_error_set_pending_exception (&error);
-}
-
-void
-ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
-{
- MonoError error;
- mono_image_build_metadata (mb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-void
-ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
-{
- mono_image_register_token (mb->dynamic_image, token, obj);
-}
-
-MonoObject*
-ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
-{
- MonoObject *obj;
-
- mono_loader_lock ();
- obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
- mono_loader_unlock ();
-
- return obj;
-}
-
-MonoReflectionModule*
-ves_icall_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
-{
- MonoError error;
- MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
/**
- * ves_icall_TypeBuilder_create_generic_class:
- * @tb: a TypeBuilder object
+ * mono_class_from_mono_type_handle:
+ * @reftype: the System.Type handle
*
- * (icall)
- * Creates the generic class after all generic parameters have been added.
+ * Returns the MonoClass* corresponding to the given type.
*/
-void
-ves_icall_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
-{
- MonoError error;
- (void) mono_reflection_create_generic_class (tb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-MonoArray*
-ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
-{
- MonoError error;
- MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-#endif
-
-void
-ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
-{
- mono_image_basic_init (assemblyb);
-}
-
-MonoBoolean
-ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
-{
- return is_generic_parameter (tb->type.type);
-}
-
-void
-ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
- MonoReflectionType *t)
-{
- enumtype->type = t->type;
-}
-
-MonoReflectionType*
-ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
-{
- MonoError error;
- MonoReflectionType *ret;
- MonoClass *klass;
- int isbyref = 0, rank;
- char *p;
- char *str = mono_string_to_utf8_checked (smodifiers, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- klass = mono_class_from_mono_type (tb->type.type);
- p = str;
- /* logic taken from mono_reflection_parse_type(): keep in sync */
- while (*p) {
- switch (*p) {
- case '&':
- if (isbyref) { /* only one level allowed by the spec */
- g_free (str);
- return NULL;
- }
- isbyref = 1;
- p++;
-
- g_free (str);
-
- ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return ret;
- case '*':
- klass = mono_ptr_class_get (&klass->byval_arg);
- mono_class_init (klass);
- p++;
- break;
- case '[':
- rank = 1;
- p++;
- while (*p) {
- if (*p == ']')
- break;
- if (*p == ',')
- rank++;
- else if (*p != '*') { /* '*' means unknown lower bound */
- g_free (str);
- return NULL;
- }
- ++p;
- }
- if (*p != ']') {
- g_free (str);
- return NULL;
- }
- p++;
- klass = mono_array_class_get (klass, rank);
- mono_class_init (klass);
- break;
- default:
- break;
- }
- }
-
- g_free (str);
-
- ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return ret;
-}
-
-void
-ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb)
-{
- mono_image_module_basic_init (moduleb);
-}
-
-guint32
-ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str)
-{
- return mono_image_insert_string (module, str);
-}
-
-void
-ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
+MonoClass*
+mono_class_from_mono_type_handle (MonoReflectionTypeHandle reftype)
{
- MonoDynamicImage *image = moduleb->dynamic_image;
-
- g_assert (type->type);
- image->wrappers_type = mono_class_from_mono_type (type->type);
+ return mono_class_from_mono_type (MONO_HANDLE_RAW (reftype)->type);
}
gboolean sgen_is_bridge_object (GCObject *obj);
void sgen_mark_bridge_object (GCObject *obj);
+gboolean sgen_bridge_handle_gc_param (const char *opt);
gboolean sgen_bridge_handle_gc_debug (const char *opt);
void sgen_bridge_print_gc_debug_usage (void);
+typedef struct {
+ char *dump_prefix;
+ gboolean accounting;
+ gboolean scc_precise_merge; // Used by Tarjan
+} SgenBridgeProcessorConfig;
+
typedef struct {
void (*reset_data) (void);
void (*processing_stw_step) (void);
MonoGCBridgeObjectKind (*class_kind) (MonoClass *klass);
void (*register_finalized_object) (GCObject *object);
void (*describe_pointer) (GCObject *object);
- void (*enable_accounting) (void);
- // Optional-- used for debugging
- void (*set_dump_prefix) (const char *prefix);
+ /* Should be called once, immediately after init */
+ void (*set_config) (const SgenBridgeProcessorConfig *);
/*
* These are set by processing_build_callback_data().
static BridgeProcessorSelection bridge_processor_selection = BRIDGE_PROCESSOR_DEFAULT;
// Most recently requested callbacks
static MonoGCBridgeCallbacks pending_bridge_callbacks;
+// Configuration to be passed to bridge processor after init
+static SgenBridgeProcessorConfig bridge_processor_config;
// Currently-in-use callbacks
MonoGCBridgeCallbacks bridge_callbacks;
}
}
+static gboolean
+bridge_processor_started ()
+{
+ return bridge_processor.reset_data != NULL;
+}
+
// Initialize a single bridge processor
static void
init_bridge_processor (SgenBridgeProcessor *processor, BridgeProcessorSelection selection)
bridge_callbacks = pending_bridge_callbacks;
// If a bridge was registered but there is no bridge processor yet
- if (bridge_callbacks.cross_references && !bridge_processor.reset_data)
+ if (bridge_callbacks.cross_references && !bridge_processor_started ()) {
init_bridge_processor (&bridge_processor, bridge_processor_selection);
+ if (bridge_processor.set_config)
+ bridge_processor.set_config (&bridge_processor_config);
+
+ // Config is no longer needed so free its memory
+ free (bridge_processor_config.dump_prefix);
+ bridge_processor_config.dump_prefix = NULL;
+ }
+
sgen_gc_unlock ();
}
}
if (selection == BRIDGE_PROCESSOR_INVALID)
g_warning ("Invalid value for bridge processor implementation, valid values are: 'new', 'old' and 'tarjan'.");
- else if (bridge_processor.reset_data)
+ else if (bridge_processor_started ())
g_warning ("Cannot set bridge processor implementation once bridge has already started");
else
bridge_processor_selection = selection;
static void
set_dump_prefix (const char *prefix)
{
- if (!bridge_processor.set_dump_prefix) {
- fprintf (stderr, "Warning: Bridge implementation does not support dumping - ignoring.\n");
- return;
- }
-
- bridge_processor.set_dump_prefix (prefix);
+ if (bridge_processor_config.dump_prefix)
+ free (bridge_processor_config.dump_prefix);
+ bridge_processor_config.dump_prefix = strdup (prefix);
}
/* Test support code */
mono_gc_register_bridge_callbacks (&callbacks);
}
+gboolean
+sgen_bridge_handle_gc_param (const char *opt)
+{
+ g_assert (!bridge_processor_started ());
+
+ if (!strcmp (opt, "bridge-require-precise-merge")) {
+ bridge_processor_config.scc_precise_merge = TRUE;
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
gboolean
sgen_bridge_handle_gc_debug (const char *opt)
{
+ g_assert (!bridge_processor_started ());
+
if (g_str_has_prefix (opt, "bridge=")) {
opt = strchr (opt, '=') + 1;
register_test_bridge_callbacks (g_strdup (opt));
} else if (!strcmp (opt, "enable-bridge-accounting")) {
- bridge_processor.enable_accounting ();
+ bridge_processor_config.accounting = TRUE;
} else if (g_str_has_prefix (opt, "bridge-dump=")) {
char *prefix = strchr (opt, '=') + 1;
- set_dump_prefix (prefix);
+ set_dump_prefix(prefix);
} else if (g_str_has_prefix (opt, "bridge-compare-to=")) {
const char *name = strchr (opt, '=') + 1;
BridgeProcessorSelection selection = bridge_processor_name (name);
if (selection != BRIDGE_PROCESSOR_INVALID) {
+ // Compare processor doesn't get config
init_bridge_processor (&compare_to_bridge_processor, selection);
} else {
g_warning ("Invalid bridge implementation to compare against - ignoring.");
* When SGen is done marking, it puts together a list of all dead bridged
* objects. This is passed to the bridge processor, which does an analysis to
* simplify the graph: It replaces strongly-connected components with single
- * nodes, and then removes any nodes corresponding to components which do not
- * contain bridged objects.
+ * nodes, and may remove nodes corresponding to components which do not contain
+ * bridged objects.
*
* The output of the SCC analysis is passed to the client's `cross_references()`
* callback. This consists of 2 arrays, an array of SCCs (MonoGCBridgeSCC),
MONO_BEGIN_DECLS
enum {
- SGEN_BRIDGE_VERSION = 4
+ SGEN_BRIDGE_VERSION = 5
};
typedef enum {
gboolean
sgen_is_critical_method (MonoMethod *method)
{
- return (method == write_barrier_conc_method || method == write_barrier_noconc_method || sgen_is_managed_allocator (method));
+ return sgen_is_managed_allocator (method);
}
gboolean
sgen_has_critical_method (void)
{
- return write_barrier_conc_method || write_barrier_noconc_method || sgen_has_managed_allocator ();
+ return sgen_has_managed_allocator ();
}
#ifndef DISABLE_JIT
return sgen_gc_invoke_finalizers ();
}
-gboolean
+MonoBoolean
mono_gc_pending_finalizers (void)
{
return sgen_have_pending_finalizers ();
} else if (g_str_has_prefix (opt, "toggleref-test")) {
/* FIXME: This should probably in MONO_GC_DEBUG */
sgen_register_test_toggleref_callback ();
- } else {
+ } else if (!sgen_bridge_handle_gc_param (opt)) {
return FALSE;
}
return TRUE;
#endif
} SCC;
+static char *dump_prefix = NULL;
+
// Maps managed objects to corresponding HashEntry stricts
static SgenHashTable hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntry), mono_aligned_addr_hash, NULL);
#endif
static void
-enable_accounting (void)
+set_config (const SgenBridgeProcessorConfig *config)
{
- SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
- bridge_accounting_enabled = TRUE;
- hash_table = table;
+ if (config->accounting) {
+ SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
+ bridge_accounting_enabled = TRUE;
+ hash_table = table;
+ }
+ if (config->dump_prefix) {
+ dump_prefix = strdup (config->dump_prefix);
+ }
}
static MonoGCBridgeObjectKind
}
#endif
-static char *dump_prefix = NULL;
-
static void
dump_graph (void)
{
fclose (file);
}
-static void
-set_dump_prefix (const char *prefix)
-{
- dump_prefix = strdup (prefix);
-}
-
static int
compare_hash_entries (const HashEntry *e1, const HashEntry *e2)
{
collector->class_kind = class_kind;
collector->register_finalized_object = register_finalized_object;
collector->describe_pointer = describe_pointer;
- collector->enable_accounting = enable_accounting;
- collector->set_dump_prefix = set_dump_prefix;
+ collector->set_config = set_config;
bridge_processor = collector;
}
static void
-enable_accounting (void)
+set_config (const SgenBridgeProcessorConfig *config)
{
- SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
- bridge_accounting_enabled = TRUE;
- hash_table = table;
+ if (config->accounting) {
+ SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
+ bridge_accounting_enabled = TRUE;
+ hash_table = table;
+ }
}
static MonoGCBridgeObjectKind
collector->class_kind = class_kind;
collector->register_finalized_object = register_finalized_object;
collector->describe_pointer = describe_pointer;
- collector->enable_accounting = enable_accounting;
+ collector->set_config = set_config;
bridge_processor = collector;
}
*/
#include "config.h"
+
#ifdef HAVE_SGEN_GC
{
return -1;
}
-
-#endif
+#else
+ #ifdef _MSC_VER
+ // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+ void __mono_win32_sgen_os_coop_quiet_lnk4221(void) {}
+ #endif
+#endif /* USE_COOP_GC */
#endif
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 ();
*/
release_gc_locks ();
+ mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation);
+
*stw_time = usec;
}
#include "sgen/sgen-gc.h"
#include "sgen-bridge-internals.h"
-#include "sgen/sgen-hash-table.h"
-#include "sgen/sgen-qsort.h"
#include "tabledefs.h"
#include "utils/mono-logger-internals.h"
* which colors. The color graph then becomes the reduced SCC graph.
*/
-static void
-enable_accounting (void)
-{
- // bridge_accounting_enabled = TRUE;
- // hash_table = (SgenHashTable)SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
-}
-
// Is this class bridged or not, and should its dependencies be scanned or not?
// The result of this callback will be cached for use by is_opaque_object later.
static MonoGCBridgeObjectKind
//enable usage logging
// #define DUMP_GRAPH 1
+/* Used in bridgeless_color_is_heavy:
+ * The idea here is as long as the reference fanin and fanout on a node are both 2 or greater, then
+ * removing that node will result in a net increase in edge count. So the question is which node
+ * removals are counterproductive (i.e., how many edges saved balances out one node added).
+ * The number of edges saved by preserving a node is (fanin*fanout - fanin - fanout).
+ *
+ * With all that in mind:
+ *
+ * - HEAVY_REFS_MIN is the number that *both* fanin and fanout must meet to preserve the node.
+ * - HEAVY_COMBINED_REFS_MIN is the number (fanin*fanout) must meet to preserve the node.
+ *
+ * Note HEAVY_COMBINED_REFS_MIN must be <= 2*INCOMING_COLORS_MAX, or we won't know the true fanin.
+ */
+
+#define HEAVY_REFS_MIN 2
+#define HEAVY_COMBINED_REFS_MIN 60
+
+/* Used in ColorData:
+ * The higher INCOMING_COLORS_BITS is the higher HEAVY_COMBINED_REFS_MIN can be (see above).
+ * However, API_INDEX_BITS + INCOMING_COLORS_BITS must be equal to 31, and if API_INDEX_BITS is too
+ * low then terrible things will happen if too many colors are generated. (The number of colors we
+ * will ever attempt to generate is currently naturally limited by the JNI GREF limit.)
+ */
+
+#define API_INDEX_BITS 26
+#define INCOMING_COLORS_BITS 5
+
+#define API_INDEX_MAX ((1<<API_INDEX_BITS)-1)
+#define INCOMING_COLORS_MAX ((1<<INCOMING_COLORS_BITS)-1)
+
// ScanData state
enum {
INITIAL,
/*
Optimizations:
We can split this data structure in two, those with bridges and those without
+ (and only bridgeless need to record incoming_colors)
*/
typedef struct {
- // Colors (ColorDatas) linked to by objects with this color
+ // Colors (ColorDatas) linked to by objects with this color
DynPtrArray other_colors;
- // Bridge objects (GCObjects) held by objects with this color
+ // Bridge objects (GCObjects) held by objects with this color
DynPtrArray bridges;
- int api_index : 31;
+ // Index of this color's MonoGCBridgeSCC in the array passed to the client (or -1 for none)
+ signed api_index : API_INDEX_BITS;
+ // Count of colors that list this color in their other_colors
+ unsigned incoming_colors : INCOMING_COLORS_BITS;
unsigned visited : 1;
} ColorData;
// Tarjan algorithm index (order visited)
int index;
// Tarjan index of lowest-index object known reachable from here
- int low_index : 27;
+ signed low_index : 27;
// See "ScanData state" enum above
unsigned state : 2;
unsigned obj_state : 2;
} ScanData;
+/* Should color be made visible to client even though it has no bridges?
+ * True if we predict the number of reduced edges to be enough to justify the extra node.
+ */
+static inline gboolean
+bridgeless_color_is_heavy (ColorData *data) {
+ int fanin = data->incoming_colors;
+ int fanout = dyn_array_ptr_size (&data->other_colors);
+ return fanin > HEAVY_REFS_MIN && fanout > HEAVY_REFS_MIN
+ && fanin*fanout >= HEAVY_COMBINED_REFS_MIN;
+}
+// Should color be made visible to client?
+static inline gboolean
+color_visible_to_client (ColorData *data) {
+ return dyn_array_ptr_size (&data->bridges) || bridgeless_color_is_heavy (data);
+}
// Stacks of ScanData objects used for tarjan algorithm.
// The Tarjan algorithm is normally defined recursively; here scan_stack simulates the call stack of a recursive algorithm,
// GCObjects on which register_finalized_object has been called
static DynPtrArray registered_bridges;
-// ColorData objects
+// As we traverse the graph, which ColorData objects are accessible from our current position?
static DynPtrArray color_merge_array;
+// Running hash of the contents of the color_merge_array.
+static unsigned int color_merge_array_hash;
+
+static void color_merge_array_empty ()
+{
+ dyn_array_ptr_empty (&color_merge_array);
+ color_merge_array_hash = 0;
+}
static int ignored_objects;
static int object_index;
static int num_colors_with_bridges;
+static int num_sccs;
static int xref_count;
static size_t setup_time, tarjan_time, scc_setup_time, gather_xref_time, xref_setup_time, cleanup_time;
static ObjectBucket *cur_object_bucket;
static int object_data_count;
+// Arenas to allocate ScanData from
static ObjectBucket*
new_object_bucket (void)
{
//ColorData buckets
#define NUM_COLOR_ENTRIES ((BUCKET_SIZE - SIZEOF_VOID_P * 2) / sizeof (ColorData))
-// Same as ObjectBucket except NUM_COLOR_ENTRIES and NUM_SCAN_ENTRIES differ
+// Arenas for ColorDatas, same as ObjectBucket except items-per-bucket differs
typedef struct _ColorBucket ColorBucket;
struct _ColorBucket {
ColorBucket *next;
//----------
typedef struct {
ColorData *color;
- int hash;
+ unsigned int hash;
} HashEntry;
/*
-We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128.
+The merge cache maps an ordered list of ColorDatas [the color_merge_array] to a single ColorData.
+
+About cache bucket tuning: We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128.
The performance cost between 4/128 and 8/128 is so small since cache movement happens completely in the same cacheline,
making the extra space pretty much free.
#define ELEMENTS_PER_BUCKET 8
#define COLOR_CACHE_SIZE 128
static HashEntry merge_cache [COLOR_CACHE_SIZE][ELEMENTS_PER_BUCKET];
+static unsigned int hash_perturb;
+
+// If true, disable an optimization where sometimes SCC nodes are merged without a perfect check
+static gboolean scc_precise_merge;
-static int
-mix_hash (size_t hash)
+static unsigned int
+mix_hash (uintptr_t source)
{
- return (int)(((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
+ unsigned int hash = source;
+
+ // The full hash determines whether two colors can be merged-- sometimes exclusively.
+ // This value changes every GC, so XORing it in before performing the hash will make the
+ // chance that two different colors will produce the same hash on successive GCs very low.
+ hash = hash ^ hash_perturb;
+
+ // Actual hash
+ hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
+
+ // Mix in highest bits on 64-bit systems only
+ if (sizeof (source) > 4)
+ hash = hash ^ (source >> 32);
+
+ return hash;
}
static void
reset_cache (void)
{
memset (merge_cache, 0, sizeof (merge_cache));
+
+ // When using the precise merge debug option, we do not want the inconsistency caused by hash_perturb.
+ if (!scc_precise_merge)
+ ++hash_perturb;
}
return FALSE;
}
+static gboolean
+match_colors_estimate (DynPtrArray *a, DynPtrArray *b)
+{
+ return dyn_array_ptr_size (a) == dyn_array_ptr_size (b);
+}
+
+
static gboolean
match_colors (DynPtrArray *a, DynPtrArray *b)
{
return TRUE;
}
-static int cache_hits, cache_misses;
+// If scc_precise_merge, "semihits" refers to find_in_cache calls aborted because the merge array was too large.
+// Otherwise "semihits" refers to cache hits where the match was only estimated.
+static int cache_hits, cache_semihits, cache_misses;
+// The cache contains only non-bridged colors.
static ColorData*
find_in_cache (int *insert_index)
{
HashEntry *bucket;
- int i, hash, size, index;
+ int i, size, index;
size = dyn_array_ptr_size (&color_merge_array);
- /* Cache checking is very ineficient with a lot of elements*/
- if (size > 3)
+
+ /* Color equality checking is very expensive with a lot of elements, so when there are many
+ * elements we switch to a cheap comparison method which allows false positives. When false
+ * positives occur the worst that can happen is two items will be inappropriately merged
+ * and memory will be retained longer than it should be. We assume that will correct itself
+ * on the next GC (the hash_perturb mechanism increases the probability of this).
+ *
+ * Because this has *some* potential to create problems, if the user set the debug option
+ * 'enable-tarjan-precise-merge' we bail out early (and never merge SCCs with >3 colors).
+ */
+ gboolean color_merge_array_large = size > 3;
+ if (scc_precise_merge && color_merge_array_large) {
+ ++cache_semihits;
return NULL;
+ }
- hash = 0;
- for (i = 0 ; i < size; ++i)
- hash += mix_hash ((size_t)dyn_array_ptr_get (&color_merge_array, i));
- if (!hash)
+ unsigned int hash = color_merge_array_hash;
+ if (!hash) // 0 is used to indicate an empty bucket entry
hash = 1;
index = hash & (COLOR_CACHE_SIZE - 1);
for (i = 0; i < ELEMENTS_PER_BUCKET; ++i) {
if (bucket [i].hash != hash)
continue;
- if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) {
- ++cache_hits;
- return bucket [i].color;
+
+ if (color_merge_array_large) {
+ if (match_colors_estimate (&bucket [i].color->other_colors, &color_merge_array)) {
+ ++cache_semihits;
+ return bucket [i].color;
+ }
+ } else {
+ if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) {
+ ++cache_hits;
+ return bucket [i].color;
+ }
}
}
return NULL;
}
+// A color is needed for an SCC. If the SCC has bridges, the color MUST be newly allocated.
+// If the SCC lacks bridges, the allocator MAY use the cache to merge it with an existing one.
static ColorData*
-new_color (gboolean force_new)
+new_color (gboolean has_bridges)
{
- int i = -1;
+ int cacheSlot = -1;
ColorData *cd;
/* XXX Try to find an equal one and return it */
- if (!force_new) {
- cd = find_in_cache (&i);
+ if (!has_bridges) {
+ cd = find_in_cache (&cacheSlot);
if (cd)
return cd;
}
cd = alloc_color_data ();
cd->api_index = -1;
dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array);
- /* if i >= 0, it means we prepared a given slot to receive the new color */
- if (i >= 0)
- merge_cache [i][0].color = cd;
+
+ // Inform targets
+ for (int i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) {
+ ColorData *points_to = (ColorData *)dyn_array_ptr_get (&color_merge_array, i);
+ points_to->incoming_colors = MIN (points_to->incoming_colors + 1, INCOMING_COLORS_MAX);
+ }
+
+ /* if cacheSlot >= 0, it means we prepared a given slot to receive the new color */
+ if (cacheSlot >= 0)
+ merge_cache [cacheSlot][0].color = cd;
return cd;
}
cd = other->color;
if (!cd->visited) {
+ color_merge_array_hash += mix_hash ((uintptr_t) other->color);
dyn_array_ptr_add (&color_merge_array, other->color);
cd->visited = TRUE;
}
#include "sgen/sgen-scan-object.h"
}
+// A non-bridged object needs a single color describing the current merge array.
static ColorData*
reduce_color (void)
{
ColorData *color = NULL;
int size = dyn_array_ptr_size (&color_merge_array);
+ // Merge array is empty-- this SCC points to no bridged colors.
+ // This SCC can be ignored completely.
if (size == 0)
color = NULL;
+
+ // Merge array has one item-- this SCC points to a single bridged color.
+ // This SCC can be forwarded to the pointed-to color.
else if (size == 1) {
color = (ColorData *)dyn_array_ptr_get (&color_merge_array, 0);
+
+ // This SCC gets to talk to the color allocator.
} else
color = new_color (FALSE);
g_assert (cd->visited);
cd->visited = FALSE;
}
- dyn_array_ptr_empty (&color_merge_array);
+ color_merge_array_empty ();
found_bridge = FALSE;
}
g_assert (dyn_array_ptr_size (&scan_stack) == 1);
g_assert (dyn_array_ptr_size (&loop_stack) == 0);
- dyn_array_ptr_empty (&color_merge_array);
+ color_merge_array_empty ();
while (dyn_array_ptr_size (&scan_stack) > 0) {
ScanData *data = (ScanData *)dyn_array_ptr_pop (&scan_stack);
if (src->visited)
continue;
src->visited = TRUE;
- if (dyn_array_ptr_size (&src->bridges))
+ if (color_visible_to_client (src))
dyn_array_ptr_add (&color_merge_array, src);
else
gather_xrefs (src);
if (!src->visited)
continue;
src->visited = FALSE;
- if (!dyn_array_ptr_size (&src->bridges))
+ if (!color_visible_to_client (src))
reset_xrefs (src);
}
}
static void
processing_build_callback_data (int generation)
{
- int j, api_index;
- MonoGCBridgeSCC **api_sccs;
- MonoGCBridgeXRef *api_xrefs;
+ int j;
gint64 curtime;
ColorBucket *cur;
printf ("number of SCCs %d\n", num_colors_with_bridges);
#endif
+ // Count the number of SCCs visible to the client
+ num_sccs = 0;
+ for (cur = root_color_bucket; cur; cur = cur->next) {
+ ColorData *cd;
+ for (cd = &cur->data [0]; cd < cur->next_data; ++cd) {
+ if (color_visible_to_client (cd))
+ num_sccs++;
+ }
+ }
+
/* This is a straightforward translation from colors to the bridge callback format. */
- api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_colors_with_bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE);
- api_index = xref_count = 0;
+ MonoGCBridgeSCC **api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA, TRUE);
+ int api_index = 0;
+ xref_count = 0;
+ // Convert visible SCCs, along with their bridged object list, to MonoGCBridgeSCCs in the client's SCC list
for (cur = root_color_bucket; cur; cur = cur->next) {
ColorData *cd;
for (cd = &cur->data [0]; cd < cur->next_data; ++cd) {
int bridges = dyn_array_ptr_size (&cd->bridges);
- if (!bridges)
+ if (!(bridges || bridgeless_color_is_heavy (cd)))
continue;
api_sccs [api_index] = (MonoGCBridgeSCC *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE);
for (j = 0; j < bridges; ++j)
api_sccs [api_index]->objs [j] = (MonoObject *)dyn_array_ptr_get (&cd->bridges, j);
+
+ g_assert(api_index < API_INDEX_MAX);
api_index++;
}
}
scc_setup_time = step_timer (&curtime);
+ // Eliminate non-visible SCCs from the SCC list and redistribute xrefs
for (cur = root_color_bucket; cur; cur = cur->next) {
ColorData *cd;
for (cd = &cur->data [0]; cd < cur->next_data; ++cd) {
- int bridges = dyn_array_ptr_size (&cd->bridges);
- if (!bridges)
+ if (!color_visible_to_client (cd))
continue;
- dyn_array_ptr_empty (&color_merge_array);
+ color_merge_array_empty ();
gather_xrefs (cd);
reset_xrefs (cd);
dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array);
dump_color_table (" after xref pass", TRUE);
#endif
- api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE);
- api_index = 0;
+ // Write out xrefs array
+ MonoGCBridgeXRef *api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE);
+ int xref_index = 0;
for (cur = root_color_bucket; cur; cur = cur->next) {
ColorData *src;
for (src = &cur->data [0]; src < cur->next_data; ++src) {
- int bridges = dyn_array_ptr_size (&src->bridges);
- if (!bridges)
+ if (!color_visible_to_client (src))
continue;
for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) {
ColorData *dest = (ColorData *)dyn_array_ptr_get (&src->other_colors, j);
- g_assert (dyn_array_ptr_size (&dest->bridges)); /* We flattened the color graph, so this must never happen. */
+ g_assert (color_visible_to_client (dest)); /* Supposedly we already eliminated all xrefs to non-visible objects. */
+
+ api_xrefs [xref_index].src_scc_index = src->api_index;
+ api_xrefs [xref_index].dst_scc_index = dest->api_index;
- api_xrefs [api_index].src_scc_index = src->api_index;
- api_xrefs [api_index].dst_scc_index = dest->api_index;
- ++api_index;
+ ++xref_index;
}
}
}
- g_assert (xref_count == api_index);
+ g_assert (xref_count == xref_index);
xref_setup_time = step_timer (&curtime);
#if defined (DUMP_GRAPH)
#endif
//FIXME move half of the cleanup to before the bridge callback?
- bridge_processor->num_sccs = num_colors_with_bridges;
+ bridge_processor->num_sccs = num_sccs;
bridge_processor->api_sccs = api_sccs;
bridge_processor->num_xrefs = xref_count;
bridge_processor->api_xrefs = api_xrefs;
int bridge_count = dyn_array_ptr_size (®istered_bridges);
int object_count = object_data_count;
int color_count = color_data_count;
- int scc_count = num_colors_with_bridges;
+ int colors_with_bridges_count = num_colors_with_bridges;
SGEN_TV_GETTIME (curtime);
cleanup_time = step_timer (&curtime);
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d colors %d ignored %d sccs %d xref %d cache %d/%d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms",
- bridge_count, object_count, color_count,
- ignored_objects, scc_count, xref_count,
- cache_hits, cache_misses,
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d opaque %d colors %d colors-bridged %d colors-visible %d xref %d cache-hit %d cache-%s %d cache-miss %d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms",
+ bridge_count, object_count, ignored_objects,
+ color_count, colors_with_bridges_count, num_sccs, xref_count,
+ cache_hits, (scc_precise_merge ? "abstain" : "semihit"), cache_semihits, cache_misses,
setup_time / 10000.0f,
tarjan_time / 10000.0f,
scc_setup_time / 10000.0f,
xref_setup_time / 10000.0f,
cleanup_time / 10000.0f);
- cache_hits = cache_misses = 0;
+ cache_hits = cache_semihits = cache_misses = 0;
ignored_objects = 0;
}
// printf (" is visited: %d\n", (int)entry->is_visited);
}
+static void
+set_config (const SgenBridgeProcessorConfig *config)
+{
+ if (config->scc_precise_merge) {
+ hash_perturb = 0;
+ scc_precise_merge = TRUE;
+ }
+}
+
void
sgen_tarjan_bridge_init (SgenBridgeProcessor *collector)
{
collector->class_kind = class_kind;
collector->register_finalized_object = register_finalized_object;
collector->describe_pointer = describe_pointer;
- collector->enable_accounting = enable_accounting;
- // collector->set_dump_prefix = set_dump_prefix;
+ collector->set_config = set_config;
sgen_register_fixed_internal_mem_type (INTERNAL_MEM_TARJAN_OBJ_BUCKET, BUCKET_SIZE);
g_assert (sizeof (ObjectBucket) <= BUCKET_SIZE);
g_assert (sizeof (ColorBucket) <= BUCKET_SIZE);
+ g_assert (API_INDEX_BITS + INCOMING_COLORS_BITS <= 31);
bridge_processor = collector;
}
MONO_EXIT_GC_SAFE;
+ if (newsock == INVALID_SOCKET)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
+ if (interrupted)
*werror = WSAEINTR;
- return NULL;
- }
- if (newsock == INVALID_SOCKET) {
- *werror = WSAGetLastError ();
+ if (*werror)
return NULL;
- }
return GUINT_TO_POINTER (newsock);
}
MONO_EXIT_GC_SAFE;
- mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
- *werror = WSAEINTR;
- return;
- }
-
if (ret == SOCKET_ERROR)
*werror = WSAGetLastError ();
+ mono_thread_info_uninstall_interrupt (&interrupted);
+ if (interrupted)
+ *werror = WSAEINTR;
+
g_free (sa);
}
MONO_ENTER_GC_SAFE;
if (_wapi_disconnectex != NULL) {
- if (!_wapi_disconnectex (sock, NULL, TF_REUSE_SOCKET, 0))
+ if (!_wapi_disconnectex (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0))
*werror = WSAGetLastError ();
} else if (_wapi_transmitfile != NULL) {
- if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | TF_REUSE_SOCKET))
+ if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0)))
*werror = WSAGetLastError ();
} else {
*werror = ERROR_NOT_SUPPORTED;
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret == SOCKET_ERROR) {
- *werror = WSAGetLastError ();
+ if (*werror)
return 0;
- }
return ret;
}
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret == SOCKET_ERROR) {
- *werror = WSAGetLastError ();
+ if (*werror)
return 0;
- }
return recv;
}
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
- g_free (sa);
+
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret==SOCKET_ERROR) {
- g_free (sa);
- *werror = WSAGetLastError ();
+ if (*werror) {
+ g_free(sa);
return 0;
}
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret == SOCKET_ERROR) {
- *werror = WSAGetLastError ();
+ if (*werror)
return 0;
- }
return ret;
}
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret == SOCKET_ERROR) {
- *werror = WSAGetLastError ();
+ if (*werror)
return 0;
- }
-
+
return sent;
}
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
- if (interrupted) {
- g_free (sa);
+ if (interrupted)
*werror = WSAEINTR;
- return 0;
- }
- if (ret == SOCKET_ERROR)
- *werror = WSAGetLastError ();
+ g_free(sa);
+
+ if (*werror)
+ return 0;
- g_free (sa);
-
return ret;
}
int system_level = 0;
int system_name = 0;
int ret;
- int val;
+ int val = 0;
socklen_t valsize = sizeof (val);
struct linger linger;
socklen_t lingersize = sizeof (linger);
MONO_EXIT_GC_SAFE;
+ if (ret == SOCKET_ERROR)
+ *werror = WSAGetLastError ();
+
mono_thread_info_uninstall_interrupt (&interrupted);
if (interrupted) {
*werror = WSAEINTR;
- return;
}
- if (ret == SOCKET_ERROR)
- *werror = WSAGetLastError ();
}
gint
--- /dev/null
+/*
+ * sre-encode.c: Routines for encoding SRE builders into a
+ * MonoDynamicImage and generating tokens.
+ *
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include "mono/metadata/dynamic-image-internals.h"
+#include "mono/metadata/dynamic-stream-internals.h"
+#include "mono/metadata/object-internals.h"
+#include "mono/metadata/sre-internals.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/tokentype.h"
+#include "mono/utils/checked-build.h"
+
+typedef struct {
+ char *p;
+ char *buf;
+ char *end;
+} SigBuffer;
+
+static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
+static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
+static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
+
+#define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
+
+static guint32
+mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+{
+ return mono_dynstream_add_data (stream, data, len);
+}
+
+static void
+alloc_table (MonoDynamicTable *table, guint nrows)
+{
+ mono_dynimage_alloc_table (table, nrows);
+}
+
+static void
+sigbuffer_init (SigBuffer *buf, int size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ buf->buf = (char *)g_malloc (size);
+ buf->p = buf->buf;
+ buf->end = buf->buf + size;
+}
+
+static void
+sigbuffer_make_room (SigBuffer *buf, int size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (buf->end - buf->p < size) {
+ int new_size = buf->end - buf->buf + size + 32;
+ char *p = (char *)g_realloc (buf->buf, new_size);
+ size = buf->p - buf->buf;
+ buf->buf = p;
+ buf->p = p + size;
+ buf->end = buf->buf + new_size;
+ }
+}
+
+static void
+sigbuffer_add_value (SigBuffer *buf, guint32 val)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ sigbuffer_make_room (buf, 6);
+ mono_metadata_encode_value (val, buf->p, &buf->p);
+}
+
+static void
+sigbuffer_add_byte (SigBuffer *buf, guint8 val)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ sigbuffer_make_room (buf, 1);
+ buf->p [0] = val;
+ buf->p++;
+}
+
+static void
+sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ sigbuffer_make_room (buf, size);
+ memcpy (buf->p, p, size);
+ buf->p += size;
+}
+
+static void
+sigbuffer_free (SigBuffer *buf)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ g_free (buf->buf);
+}
+
+static guint32
+sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ char blob_size [8];
+ char *b = blob_size;
+ guint32 size = buf->p - buf->buf;
+ /* store length */
+ g_assert (size <= (buf->end - buf->buf));
+ mono_metadata_encode_value (size, b, &b);
+ return mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
+}
+
+
+static void
+encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ int i;
+ MonoGenericInst *class_inst;
+ MonoClass *klass;
+
+ g_assert (gclass);
+
+ class_inst = gclass->context.class_inst;
+
+ sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
+ klass = gclass->container_class;
+ sigbuffer_add_value (buf, klass->byval_arg.type);
+ sigbuffer_add_value (buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
+
+ sigbuffer_add_value (buf, class_inst->type_argc);
+ for (i = 0; i < class_inst->type_argc; ++i)
+ encode_type (assembly, class_inst->type_argv [i], buf);
+
+}
+
+static void
+encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (!type) {
+ g_assert_not_reached ();
+ return;
+ }
+
+ if (type->byref)
+ sigbuffer_add_value (buf, MONO_TYPE_BYREF);
+
+ switch (type->type){
+ case MONO_TYPE_VOID:
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_TYPEDBYREF:
+ sigbuffer_add_value (buf, type->type);
+ break;
+ case MONO_TYPE_PTR:
+ sigbuffer_add_value (buf, type->type);
+ encode_type (assembly, type->data.type, buf);
+ break;
+ case MONO_TYPE_SZARRAY:
+ sigbuffer_add_value (buf, type->type);
+ encode_type (assembly, &type->data.klass->byval_arg, buf);
+ break;
+ case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_CLASS: {
+ MonoClass *k = mono_class_from_mono_type (type);
+
+ if (k->generic_container) {
+ MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
+ encode_generic_class (assembly, gclass, buf);
+ } else {
+ /*
+ * Make sure we use the correct type.
+ */
+ sigbuffer_add_value (buf, k->byval_arg.type);
+ /*
+ * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
+ * otherwise two typerefs could point to the same type, leading to
+ * verification errors.
+ */
+ sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
+ }
+ break;
+ }
+ case MONO_TYPE_ARRAY:
+ sigbuffer_add_value (buf, type->type);
+ encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
+ sigbuffer_add_value (buf, type->data.array->rank);
+ sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
+ sigbuffer_add_value (buf, 0);
+ break;
+ case MONO_TYPE_GENERICINST:
+ encode_generic_class (assembly, type->data.generic_class, buf);
+ break;
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ sigbuffer_add_value (buf, type->type);
+ sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
+ break;
+ default:
+ g_error ("need to encode type %x", type->type);
+ }
+}
+
+static void
+encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ if (!type) {
+ sigbuffer_add_value (buf, MONO_TYPE_VOID);
+ return;
+ }
+
+ MonoType *t = mono_reflection_type_get_handle (type, error);
+ return_if_nok (error);
+ encode_type (assembly, t, buf);
+}
+
+static void
+encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ int i;
+
+ mono_error_init (error);
+
+ if (modreq) {
+ for (i = 0; i < mono_array_length (modreq); ++i) {
+ MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
+ return_if_nok (error);
+ sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
+ sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
+ }
+ }
+ if (modopt) {
+ for (i = 0; i < mono_array_length (modopt); ++i) {
+ MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
+ return_if_nok (error);
+ sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
+ sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
+ }
+ }
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+guint32
+mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ SigBuffer buf;
+ int i;
+ guint32 nparams = sig->param_count;
+ guint32 idx;
+
+ if (!assembly->save)
+ return 0;
+
+ sigbuffer_init (&buf, 32);
+ /*
+ * FIXME: vararg, explicit_this, differenc call_conv values...
+ */
+ idx = sig->call_convention;
+ if (sig->hasthis)
+ idx |= 0x20; /* hasthis */
+ if (sig->generic_param_count)
+ idx |= 0x10; /* generic */
+ sigbuffer_add_byte (&buf, idx);
+ if (sig->generic_param_count)
+ sigbuffer_add_value (&buf, sig->generic_param_count);
+ sigbuffer_add_value (&buf, nparams);
+ encode_type (assembly, sig->ret, &buf);
+ for (i = 0; i < nparams; ++i) {
+ if (i == sig->sentinelpos)
+ sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
+ encode_type (assembly, sig->params [i], &buf);
+ }
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+guint32
+mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+#endif
+
+guint32
+mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ /*
+ * FIXME: reuse code from method_encode_signature().
+ */
+ SigBuffer buf;
+ int i;
+ guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
+ guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
+ guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
+ guint32 idx;
+
+ sigbuffer_init (&buf, 32);
+ /* LAMESPEC: all the call conv spec is foobared */
+ idx = mb->call_conv & 0x60; /* has-this, explicit-this */
+ if (mb->call_conv & 2)
+ idx |= 0x5; /* vararg */
+ if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
+ idx |= 0x20; /* hasthis */
+ if (ngparams)
+ idx |= 0x10; /* generic */
+ sigbuffer_add_byte (&buf, idx);
+ if (ngparams)
+ sigbuffer_add_value (&buf, ngparams);
+ sigbuffer_add_value (&buf, nparams + notypes);
+ encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
+ if (!is_ok (error))
+ goto leave;
+ encode_reflection_type (assembly, mb->rtype, &buf, error);
+ if (!is_ok (error))
+ goto leave;
+ for (i = 0; i < nparams; ++i) {
+ MonoArray *modreq = NULL;
+ MonoArray *modopt = NULL;
+ MonoReflectionType *pt;
+
+ if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
+ modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
+ if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
+ modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
+ encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
+ if (!is_ok (error))
+ goto leave;
+ pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, &buf, error);
+ if (!is_ok (error))
+ goto leave;
+ }
+ if (notypes)
+ sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
+ for (i = 0; i < notypes; ++i) {
+ MonoReflectionType *pt;
+
+ pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, &buf, error);
+ if (!is_ok (error))
+ goto leave;
+ }
+
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+leave:
+ sigbuffer_free (&buf);
+ return idx;
+}
+
+guint32
+mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 idx, sig_idx;
+ guint nl = mono_array_length (ilgen->locals);
+ SigBuffer buf;
+ int i;
+
+ sigbuffer_init (&buf, 32);
+ sigbuffer_add_value (&buf, 0x07);
+ sigbuffer_add_value (&buf, nl);
+ for (i = 0; i < nl; ++i) {
+ MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
+
+ if (lb->is_pinned)
+ sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
+
+ encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
+ if (!is_ok (error)) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ }
+ sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+
+ if (assembly->standalonesig_cache == NULL)
+ assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
+ idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
+ if (idx)
+ return idx;
+
+ table = &assembly->tables [MONO_TABLE_STANDALONESIG];
+ idx = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
+
+ values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
+
+ g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
+
+ return idx;
+}
+
+
+/*
+ * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
+ * dest may be misaligned.
+ */
+static void
+swap_with_size (char *dest, const char* val, int len, int nelem) {
+ MONO_REQ_GC_NEUTRAL_MODE;
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ int elem;
+
+ for (elem = 0; elem < nelem; ++elem) {
+ switch (len) {
+ case 1:
+ *dest = *val;
+ break;
+ case 2:
+ dest [0] = val [1];
+ dest [1] = val [0];
+ break;
+ case 4:
+ dest [0] = val [3];
+ dest [1] = val [2];
+ dest [2] = val [1];
+ dest [3] = val [0];
+ break;
+ case 8:
+ dest [0] = val [7];
+ dest [1] = val [6];
+ dest [2] = val [5];
+ dest [3] = val [4];
+ dest [4] = val [3];
+ dest [5] = val [2];
+ dest [6] = val [1];
+ dest [7] = val [0];
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ dest += len;
+ val += len;
+ }
+#else
+ memcpy (dest, val, len * nelem);
+#endif
+}
+
+
+guint32
+mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ char blob_size [64];
+ char *b = blob_size;
+ char *box_val;
+ char* buf;
+ guint32 idx = 0, len = 0, dummy = 0;
+
+ buf = (char *)g_malloc (64);
+ if (!val) {
+ *ret_type = MONO_TYPE_CLASS;
+ len = 4;
+ box_val = (char*)&dummy;
+ } else {
+ box_val = ((char*)val) + sizeof (MonoObject);
+ *ret_type = val->vtable->klass->byval_arg.type;
+ }
+handle_enum:
+ switch (*ret_type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ len = 1;
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ len = 2;
+ break;
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_R4:
+ len = 4;
+ break;
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ len = 8;
+ break;
+ case MONO_TYPE_R8:
+ len = 8;
+ break;
+ case MONO_TYPE_VALUETYPE: {
+ MonoClass *klass = val->vtable->klass;
+
+ if (klass->enumtype) {
+ *ret_type = mono_class_enum_basetype (klass)->type;
+ goto handle_enum;
+ } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
+ len = 8;
+ } else
+ g_error ("we can't encode valuetypes, we should have never reached this line");
+ break;
+ }
+ case MONO_TYPE_CLASS:
+ break;
+ case MONO_TYPE_STRING: {
+ MonoString *str = (MonoString*)val;
+ /* there is no signature */
+ len = str->length * 2;
+ mono_metadata_encode_value (len, b, &b);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ {
+ char *swapped = g_malloc (2 * mono_string_length (str));
+ const char *p = (const char*)mono_string_chars (str);
+
+ swap_with_size (swapped, p, 2, mono_string_length (str));
+ idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
+ g_free (swapped);
+ }
+#else
+ idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
+#endif
+
+ g_free (buf);
+ return idx;
+ }
+ case MONO_TYPE_GENERICINST:
+ *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
+ goto handle_enum;
+ default:
+ g_error ("we don't encode constant type 0x%02x yet", *ret_type);
+ }
+
+ /* there is no signature */
+ mono_metadata_encode_value (len, b, &b);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ swap_with_size (blob_size, box_val, len, 1);
+ mono_image_add_stream_data (&assembly->blob, blob_size, len);
+#else
+ idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
+#endif
+
+ g_free (buf);
+ return idx;
+}
+
+
+guint32
+mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ SigBuffer buf;
+ guint32 idx;
+ guint32 typespec = 0;
+ MonoType *type;
+ MonoClass *klass;
+
+ mono_reflection_init_type_builder_generics (fb->type, error);
+ return_val_if_nok (error, 0);
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, 0x06);
+ encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ /* encode custom attributes before the type */
+
+ if (klass->generic_container)
+ typespec = create_typespec (assembly, type);
+
+ if (typespec) {
+ MonoGenericClass *gclass;
+ gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
+ encode_generic_class (assembly, gclass, &buf);
+ } else {
+ encode_type (assembly, type, &buf);
+ }
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+fail:
+ sigbuffer_free (&buf);
+ return 0;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+/*field_image is the image to which the eventual custom mods have been encoded against*/
+guint32
+mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ SigBuffer buf;
+ guint32 idx, i, token;
+
+ if (!assembly->save)
+ return 0;
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, 0x06);
+ /* encode custom attributes before the type */
+ if (type->num_mods) {
+ for (i = 0; i < type->num_mods; ++i) {
+ if (field_image) {
+ MonoError error;
+ MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
+ token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
+ } else {
+ token = type->modifiers [i].token;
+ }
+
+ if (type->modifiers [i].required)
+ sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
+ else
+ sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
+
+ sigbuffer_add_value (&buf, token);
+ }
+ }
+ encode_type (assembly, type, &buf);
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+guint32
+mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+#endif /* DISABLE_REFLECTION_EMIT */
+
+static guint32
+create_typespec (MonoDynamicImage *assembly, MonoType *type)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token;
+ SigBuffer buf;
+
+ if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
+ return token;
+
+ sigbuffer_init (&buf, 32);
+ switch (type->type) {
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ case MONO_TYPE_GENERICINST:
+ encode_type (assembly, type, &buf);
+ break;
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE: {
+ MonoClass *k = mono_class_from_mono_type (type);
+ if (!k || !k->generic_container) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ encode_type (assembly, type, &buf);
+ break;
+ }
+ default:
+ sigbuffer_free (&buf);
+ return 0;
+ }
+
+ table = &assembly->tables [MONO_TABLE_TYPESPEC];
+ if (assembly->save) {
+ token = sigbuffer_add_to_blob_cached (assembly, &buf);
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+ values [MONO_TYPESPEC_SIGNATURE] = token;
+ }
+ sigbuffer_free (&buf);
+
+ token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
+ g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
+ table->next_idx ++;
+ return token;
+}
+
+guint32
+mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token, scope, enclosing;
+ MonoClass *klass;
+
+ /* if the type requires a typespec, we must try that first*/
+ if (try_typespec && (token = create_typespec (assembly, type)))
+ return token;
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
+ if (token)
+ return token;
+ klass = mono_class_from_mono_type (type);
+ if (!klass)
+ klass = mono_class_from_mono_type (type);
+
+ /*
+ * If it's in the same module and not a generic type parameter:
+ */
+ if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
+ (type->type != MONO_TYPE_MVAR)) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
+ mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
+ return token;
+ }
+
+ if (klass->nested_in) {
+ enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
+ /* get the typeref idx of the enclosing type */
+ enclosing >>= MONO_TYPEDEFORREF_BITS;
+ scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
+ } else {
+ scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
+ }
+ table = &assembly->tables [MONO_TABLE_TYPEREF];
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
+ values [MONO_TYPEREF_SCOPE] = scope;
+ values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, klass->name);
+ values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, klass->name_space);
+ }
+ token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
+ g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
+ table->next_idx ++;
+ mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
+ return token;
+}
+
+/*
+ * Despite the name, we handle also TypeSpec (with the above helper).
+ */
+static guint32
+mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
+{
+ return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
+}
+
+guint32
+mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
+{
+ SigBuffer buf;
+ int i;
+ guint32 nparams = mono_array_length (mb->generic_params);
+ guint32 idx;
+
+ if (!assembly->save)
+ return 0;
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, 0xa);
+ sigbuffer_add_value (&buf, nparams);
+
+ for (i = 0; i < nparams; i++) {
+ sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
+ sigbuffer_add_value (&buf, i);
+ }
+
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+}
+
+guint32
+mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
+{
+ SigBuffer buf;
+ int i;
+ guint32 nparams = context->method_inst->type_argc;
+ guint32 idx;
+
+ if (!assembly->save)
+ return 0;
+
+ sigbuffer_init (&buf, 32);
+ /*
+ * FIXME: vararg, explicit_this, differenc call_conv values...
+ */
+ sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
+ sigbuffer_add_value (&buf, nparams);
+
+ for (i = 0; i < nparams; i++)
+ encode_type (assembly, context->method_inst->type_argv [i], &buf);
+
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+guint32
+mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
+{
+ MonoDynamicTable *table;
+ MonoClass *klass;
+ MonoType *type;
+ guint32 *values;
+ guint32 token;
+ SigBuffer buf;
+ int count, i;
+
+ /*
+ * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
+ * ie. what we'd normally use as the generic type in a TypeSpec signature.
+ * Because of this, we must not insert it into the `typeref' hash table.
+ */
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+ return_val_if_nok (error, 0);
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
+ if (token)
+ return token;
+
+ sigbuffer_init (&buf, 32);
+
+ g_assert (tb->generic_params);
+ klass = mono_class_from_mono_type (type);
+
+ if (tb->generic_container) {
+ if (!mono_reflection_create_generic_class (tb, error))
+ goto fail;
+ }
+
+ sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
+ g_assert (klass->generic_container);
+ sigbuffer_add_value (&buf, klass->byval_arg.type);
+ sigbuffer_add_value (&buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
+
+ count = mono_array_length (tb->generic_params);
+ sigbuffer_add_value (&buf, count);
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gparam;
+
+ gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
+ MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
+ if (!is_ok (error))
+ goto fail;
+
+ encode_type (assembly, gparam_type, &buf);
+ }
+
+ table = &assembly->tables [MONO_TABLE_TYPESPEC];
+
+ if (assembly->save) {
+ token = sigbuffer_add_to_blob_cached (assembly, &buf);
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+ values [MONO_TYPESPEC_SIGNATURE] = token;
+ }
+ sigbuffer_free (&buf);
+
+ token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
+ g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
+ table->next_idx ++;
+ return token;
+fail:
+ sigbuffer_free (&buf);
+ return 0;
+}
+#else /*DISABLE_REFLECTION_EMIT*/
+guint32
+mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+#endif /*DISABLE_REFLECTION_EMIT*/
+
+#ifndef DISABLE_REFLECTION_EMIT
+guint32
+mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
+{
+ SigBuffer buf;
+ guint32 nargs;
+ guint32 i, idx;
+
+ mono_error_init (error);
+
+ if (!assembly->save)
+ return 0;
+
+ /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
+ g_assert (helper->type == 2);
+
+ if (helper->arguments)
+ nargs = mono_array_length (helper->arguments);
+ else
+ nargs = 0;
+
+ sigbuffer_init (&buf, 32);
+
+ /* Encode calling convention */
+ /* Change Any to Standard */
+ if ((helper->call_conv & 0x03) == 0x03)
+ helper->call_conv = 0x01;
+ /* explicit_this implies has_this */
+ if (helper->call_conv & 0x40)
+ helper->call_conv &= 0x20;
+
+ if (helper->call_conv == 0) { /* Unmanaged */
+ idx = helper->unmanaged_call_conv - 1;
+ } else {
+ /* Managed */
+ idx = helper->call_conv & 0x60; /* has_this + explicit_this */
+ if (helper->call_conv & 0x02) /* varargs */
+ idx += 0x05;
+ }
+
+ sigbuffer_add_byte (&buf, idx);
+ sigbuffer_add_value (&buf, nargs);
+ encode_reflection_type (assembly, helper->return_type, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ for (i = 0; i < nargs; ++i) {
+ MonoArray *modreqs = NULL;
+ MonoArray *modopts = NULL;
+ MonoReflectionType *pt;
+
+ if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
+ modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
+ if (helper->modopts && (i < mono_array_length (helper->modopts)))
+ modopts = mono_array_get (helper->modopts, MonoArray*, i);
+
+ encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+
+ return idx;
+fail:
+ sigbuffer_free (&buf);
+ return 0;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+guint32
+mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+#endif /* DISABLE_REFLECTION_EMIT */
+
+static MonoArray *
+reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
+{
+ MonoReflectionModuleBuilder *module = sig->module;
+ MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
+ guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
+ guint32 buflen, i;
+ MonoArray *result;
+ SigBuffer buf;
+
+ mono_error_init (error);
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, 0x07);
+ sigbuffer_add_value (&buf, na);
+ if (assembly != NULL){
+ for (i = 0; i < na; ++i) {
+ MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
+ encode_reflection_type (assembly, type, &buf, error);
+ if (!is_ok (error)) goto fail;
+ }
+ }
+
+ buflen = buf.p - buf.buf;
+ result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
+ if (!is_ok (error)) goto fail;
+ memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
+ sigbuffer_free (&buf);
+ return result;
+fail:
+ sigbuffer_free (&buf);
+ return NULL;
+}
+
+static MonoArray *
+reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
+{
+ MonoDynamicImage *assembly = sig->module->dynamic_image;
+ guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
+ guint32 buflen, i;
+ MonoArray *result;
+ SigBuffer buf;
+
+ mono_error_init (error);
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, 0x06);
+ for (i = 0; i < na; ++i) {
+ MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
+ encode_reflection_type (assembly, type, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+
+ buflen = buf.p - buf.buf;
+ result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
+ if (!is_ok (error)) goto fail;
+ memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
+ sigbuffer_free (&buf);
+
+ return result;
+fail:
+ sigbuffer_free (&buf);
+ return NULL;
+}
+
+static char*
+type_get_fully_qualified_name (MonoType *type)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT_SAVE
+guint32
+mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ char *str;
+ SigBuffer buf;
+ guint32 idx, len;
+
+ sigbuffer_init (&buf, 32);
+
+ sigbuffer_add_value (&buf, minfo->type);
+
+ switch (minfo->type) {
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ sigbuffer_add_value (&buf, minfo->count);
+ break;
+ case MONO_NATIVE_LPARRAY:
+ if (minfo->eltype || minfo->has_size) {
+ sigbuffer_add_value (&buf, minfo->eltype);
+ if (minfo->has_size) {
+ sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
+ sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
+
+ /* LAMESPEC: ElemMult is undocumented */
+ sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
+ }
+ }
+ break;
+ case MONO_NATIVE_SAFEARRAY:
+ if (minfo->eltype)
+ sigbuffer_add_value (&buf, minfo->eltype);
+ break;
+ case MONO_NATIVE_CUSTOM:
+ if (minfo->guid) {
+ str = mono_string_to_utf8_checked (minfo->guid, error);
+ if (!is_ok (error)) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ len = strlen (str);
+ sigbuffer_add_value (&buf, len);
+ sigbuffer_add_mem (&buf, str, len);
+ g_free (str);
+ } else {
+ sigbuffer_add_value (&buf, 0);
+ }
+ /* native type name */
+ sigbuffer_add_value (&buf, 0);
+ /* custom marshaler type name */
+ if (minfo->marshaltype || minfo->marshaltyperef) {
+ if (minfo->marshaltyperef) {
+ MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
+ if (!is_ok (error)) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ str = type_get_fully_qualified_name (marshaltype);
+ } else {
+ str = mono_string_to_utf8_checked (minfo->marshaltype, error);
+ if (!is_ok (error)) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ }
+ len = strlen (str);
+ sigbuffer_add_value (&buf, len);
+ sigbuffer_add_mem (&buf, str, len);
+ g_free (str);
+ } else {
+ /* FIXME: Actually a bug, since this field is required. Punting for now ... */
+ sigbuffer_add_value (&buf, 0);
+ }
+ if (minfo->mcookie) {
+ str = mono_string_to_utf8_checked (minfo->mcookie, error);
+ if (!is_ok (error)) {
+ sigbuffer_free (&buf);
+ return 0;
+ }
+ len = strlen (str);
+ sigbuffer_add_value (&buf, len);
+ sigbuffer_add_mem (&buf, str, len);
+ g_free (str);
+ } else {
+ sigbuffer_add_value (&buf, 0);
+ }
+ break;
+ default:
+ break;
+ }
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+}
+
+guint32
+mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ SigBuffer buf;
+ guint32 nparams = 0;
+ MonoReflectionMethodBuilder *mb = fb->get_method;
+ MonoReflectionMethodBuilder *smb = fb->set_method;
+ guint32 idx, i;
+
+ if (mb && mb->parameters)
+ nparams = mono_array_length (mb->parameters);
+ if (!mb && smb && smb->parameters)
+ nparams = mono_array_length (smb->parameters) - 1;
+ sigbuffer_init (&buf, 32);
+ if (fb->call_conv & 0x20)
+ sigbuffer_add_byte (&buf, 0x28);
+ else
+ sigbuffer_add_byte (&buf, 0x08);
+ sigbuffer_add_value (&buf, nparams);
+ if (mb) {
+ encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ for (i = 0; i < nparams; ++i) {
+ MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+ } else if (smb && smb->parameters) {
+ /* the property type is the last param */
+ encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
+ if (!is_ok (error))
+ goto fail;
+
+ for (i = 0; i < nparams; ++i) {
+ MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+ } else {
+ encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+
+ idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+ sigbuffer_free (&buf);
+ return idx;
+fail:
+ sigbuffer_free (&buf);
+ return 0;
+}
+
+
+#else /*DISABLE_REFLECTION_EMIT_SAVE*/
+guint32
+mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+
+guint32
+mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+#endif /*DISABLE_REFLECTION_EMIT_SAVE*/
+
+#ifndef DISABLE_REFLECTION_EMIT
+MonoArray *
+ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
+{
+ MonoError error;
+ MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+MonoArray *
+ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
+{
+ MonoError error;
+ MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+MonoArray *
+ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+MonoArray *
+ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+#endif /* DISABLE_REFLECTION_EMIT */
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_SRE_INTERNALS_H__
+#define __MONO_METADATA_SRE_INTERNALS_H__
+
+#include <mono/metadata/object-internals.h>
+
+typedef struct _ArrayMethod ArrayMethod;
+
+typedef struct {
+ guint32 owner;
+ MonoReflectionGenericParam *gparam;
+} GenericParamTableEntry;
+
+typedef struct {
+ MonoReflectionILGen *ilgen;
+ MonoReflectionType *rtype;
+ MonoArray *parameters;
+ MonoArray *generic_params;
+ MonoGenericContainer *generic_container;
+ MonoArray *pinfo;
+ MonoArray *opt_types;
+ guint32 attrs;
+ guint32 iattrs;
+ guint32 call_conv;
+ guint32 *table_idx; /* note: it's a pointer */
+ MonoArray *code;
+ MonoObject *type;
+ MonoString *name;
+ MonoBoolean init_locals;
+ MonoBoolean skip_visibility;
+ MonoArray *return_modreq;
+ MonoArray *return_modopt;
+ MonoArray *param_modreq;
+ MonoArray *param_modopt;
+ MonoArray *permissions;
+ MonoMethod *mhandle;
+ guint32 nrefs;
+ gpointer *refs;
+ /* for PInvoke */
+ int charset, extra_flags, native_cc;
+ MonoString *dll, *dllentry;
+} ReflectionMethodBuilder;
+
+void
+mono_reflection_emit_init (void);
+
+void
+mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb);
+
+gpointer
+mono_image_g_malloc0 (MonoImage *image, guint size);
+
+gboolean
+mono_is_sre_type_builder (MonoClass *klass);
+
+gboolean
+mono_is_sre_generic_instance (MonoClass *klass);
+
+gboolean
+mono_is_sre_method_on_tb_inst (MonoClass *klass);
+
+gboolean
+mono_is_sre_ctor_builder (MonoClass *klass);
+
+gboolean
+mono_is_sre_ctor_on_tb_inst (MonoClass *klass);
+
+gboolean
+mono_is_sr_mono_cmethod (MonoClass *klass);
+
+gboolean
+mono_is_sr_mono_property (MonoClass *klass);
+
+gboolean
+mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error);
+
+MonoMethod*
+mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error);
+
+MonoMethod*
+mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error);
+
+gpointer
+mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
+
+void
+mono_sre_array_method_free (ArrayMethod *am);
+
+void
+mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry);
+
+gboolean
+mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb,
+ MonoError *error);
+gboolean
+mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb,
+ MonoError *error);
+
+void
+mono_reflection_init_type_builder_generics (MonoObject *type, MonoError *error);
+
+guint32
+mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image);
+
+guint32 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen);
+
+
+/* sre-encode */
+
+guint32
+mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error);
+
+guint32
+mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type);
+
+guint32
+mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error);
+
+guint32
+mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type);
+
+guint32
+mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig);
+
+guint32
+mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb,
+ MonoError *error);
+
+guint32
+mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
+
+guint32
+mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
+
+guint32
+mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
+
+guint32
+mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
+
+guint32
+mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper,
+ MonoError *error);
+
+/* sre-encode, without DISABLE_REFLECTION_EMIT_SAVE (o.w. g_assert_not_reached ()) */
+
+guint32
+mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
+
+guint32
+mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error);
+
+#endif /* __MONO_METADATA_SRE_INTERNALS_H__ */
+
--- /dev/null
+/*
+ * sre-save.c: Routine for saving an image to a file.
+ *
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/metadata/dynamic-image-internals.h"
+#include "mono/metadata/dynamic-stream-internals.h"
+#include "mono/metadata/mono-ptr-array.h"
+#include "mono/metadata/object-internals.h"
+#include "mono/metadata/sre-internals.h"
+#include "mono/metadata/security-manager.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/tokentype.h"
+
+#include "mono/utils/checked-build.h"
+#include "mono/utils/mono-digest.h"
+#include "mono/utils/mono-error-internals.h"
+
+#define TEXT_OFFSET 512
+#define CLI_H_SIZE 136
+#define FILE_ALIGN 512
+#define VIRT_ALIGN 8192
+#define START_TEXT_RVA 0x00002000
+
+static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
+
+static void
+alloc_table (MonoDynamicTable *table, guint nrows)
+{
+ mono_dynimage_alloc_table (table, nrows);
+}
+
+static guint32
+string_heap_insert (MonoDynamicStream *sh, const char *str)
+{
+ return mono_dynstream_insert_string (sh, str);
+}
+
+static guint32
+string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
+{
+ return mono_dynstream_insert_mstring (sh, str, error);
+}
+
+static guint32
+mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+{
+ return mono_dynstream_add_data (stream, data, len);
+}
+
+static guint32
+mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
+{
+ return mono_dynstream_add_zero (stream, len);
+}
+
+static void
+stream_data_align (MonoDynamicStream *stream)
+{
+ mono_dynstream_data_align (stream);
+}
+
+static guint32
+mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
+{
+ return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
+}
+
+static guint32
+find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ int i;
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ table = &assembly->tables [table_idx];
+
+ g_assert (col < table->columns);
+
+ values = table->values + table->columns;
+ for (i = 1; i <= table->rows; ++i) {
+ if (values [col] == token)
+ return i;
+ values += table->columns;
+ }
+ return 0;
+}
+
+/*
+ * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
+ * dest may be misaligned.
+ */
+static void
+swap_with_size (char *dest, const char* val, int len, int nelem) {
+ MONO_REQ_GC_NEUTRAL_MODE;
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ int elem;
+
+ for (elem = 0; elem < nelem; ++elem) {
+ switch (len) {
+ case 1:
+ *dest = *val;
+ break;
+ case 2:
+ dest [0] = val [1];
+ dest [1] = val [0];
+ break;
+ case 4:
+ dest [0] = val [3];
+ dest [1] = val [2];
+ dest [2] = val [1];
+ dest [3] = val [0];
+ break;
+ case 8:
+ dest [0] = val [7];
+ dest [1] = val [6];
+ dest [2] = val [5];
+ dest [3] = val [4];
+ dest [4] = val [3];
+ dest [5] = val [2];
+ dest [6] = val [1];
+ dest [7] = val [0];
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ dest += len;
+ val += len;
+ }
+#else
+ memcpy (dest, val, len * nelem);
+#endif
+}
+
+static guint32
+add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ char blob_size [64];
+ char *b = blob_size;
+ guint32 idx = 0, len;
+
+ len = str->length * 2;
+ mono_metadata_encode_value (len, b, &b);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ {
+ char *swapped = g_malloc (2 * mono_string_length (str));
+ const char *p = (const char*)mono_string_chars (str);
+
+ swap_with_size (swapped, p, 2, mono_string_length (str));
+ idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
+ g_free (swapped);
+ }
+#else
+ idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
+#endif
+ return idx;
+}
+
+/*
+ * idx is the table index of the object
+ * type is one of MONO_CUSTOM_ATTR_*
+ */
+static gboolean
+mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ MonoReflectionCustomAttr *cattr;
+ guint32 *values;
+ guint32 count, i, token;
+ char blob_size [6];
+ char *p = blob_size;
+
+ mono_error_init (error);
+
+ /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
+ if (!cattrs)
+ return TRUE;
+ count = mono_array_length (cattrs);
+ table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+ table->rows += count;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= type;
+ for (i = 0; i < count; ++i) {
+ cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+ values [MONO_CUSTOM_ATTR_PARENT] = idx;
+ token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
+ if (!mono_error_ok (error)) goto fail;
+ type = mono_metadata_token_index (token);
+ type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (mono_metadata_token_table (token)) {
+ case MONO_TABLE_METHOD:
+ type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+ /*
+ * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
+ * method, not the one returned by mono_image_create_token ().
+ */
+ mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
+ break;
+ case MONO_TABLE_MEMBERREF:
+ type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
+ break;
+ default:
+ g_warning ("got wrong token in custom attr");
+ continue;
+ }
+ values [MONO_CUSTOM_ATTR_TYPE] = type;
+ p = blob_size;
+ mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
+ values [MONO_CUSTOM_ATTR_VALUE] = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, p - blob_size,
+ mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
+ values += MONO_CUSTOM_ATTR_SIZE;
+ ++table->next_idx;
+ }
+
+ return TRUE;
+
+fail:
+ return FALSE;
+}
+
+static void
+mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 count, i, idx;
+ MonoReflectionPermissionSet *perm;
+
+ if (!permissions)
+ return;
+
+ count = mono_array_length (permissions);
+ table = &assembly->tables [MONO_TABLE_DECLSECURITY];
+ table->rows += count;
+ alloc_table (table, table->rows);
+
+ for (i = 0; i < mono_array_length (permissions); ++i) {
+ perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
+
+ values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
+
+ idx = mono_metadata_token_index (parent_token);
+ idx <<= MONO_HAS_DECL_SECURITY_BITS;
+ switch (mono_metadata_token_table (parent_token)) {
+ case MONO_TABLE_TYPEDEF:
+ idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
+ break;
+ case MONO_TABLE_METHOD:
+ idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
+ break;
+ case MONO_TABLE_ASSEMBLY:
+ idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ values [MONO_DECL_SECURITY_ACTION] = perm->action;
+ values [MONO_DECL_SECURITY_PARENT] = idx;
+ values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
+
+ ++table->next_idx;
+ }
+}
+
+/**
+ * method_encode_code:
+ *
+ * @assembly the assembly
+ * @mb the managed MethodBuilder
+ * @error set on error
+ *
+ * Note that the return value is not sensible if @error is set.
+ */
+static guint32
+method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ char flags = 0;
+ guint32 idx;
+ guint32 code_size;
+ gint32 max_stack, i;
+ gint32 num_locals = 0;
+ gint32 num_exception = 0;
+ gint maybe_small;
+ guint32 fat_flags;
+ char fat_header [12];
+ guint32 int_value;
+ guint16 short_value;
+ guint32 local_sig = 0;
+ guint32 header_size = 12;
+ MonoArray *code;
+
+ mono_error_init (error);
+
+ if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
+ (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
+ return 0;
+
+ /*if (mb->name)
+ g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
+ if (mb->ilgen) {
+ code = mb->ilgen->code;
+ code_size = mb->ilgen->code_len;
+ max_stack = mb->ilgen->max_stack;
+ num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
+ if (mb->ilgen->ex_handlers)
+ num_exception = mono_reflection_method_count_clauses (mb->ilgen);
+ } else {
+ code = mb->code;
+ if (code == NULL){
+ MonoError inner_error;
+ char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
+ if (!is_ok (&inner_error)) {
+ name = g_strdup ("");
+ mono_error_cleanup (&inner_error);
+ }
+ char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
+ mono_error_set_argument (error, NULL, "a method does not have any IL associated");
+ g_free (str);
+ g_free (name);
+ return 0;
+ }
+
+ code_size = mono_array_length (code);
+ max_stack = 8; /* we probably need to run a verifier on the code... */
+ }
+
+ stream_data_align (&assembly->code);
+
+ /* check for exceptions, maxstack, locals */
+ maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
+ if (maybe_small) {
+ if (code_size < 64 && !(code_size & 1)) {
+ flags = (code_size << 2) | 0x2;
+ } else if (code_size < 32 && (code_size & 1)) {
+ flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
+ } else {
+ goto fat_header;
+ }
+ idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
+ /* add to the fixup todo list */
+ if (mb->ilgen && mb->ilgen->num_token_fixups)
+ mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
+ mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
+ return assembly->text_rva + idx;
+ }
+fat_header:
+ if (num_locals) {
+ local_sig = MONO_TOKEN_SIGNATURE | mono_dynimage_encode_locals (assembly, mb->ilgen, error);
+ return_val_if_nok (error, 0);
+ }
+ /*
+ * FIXME: need to set also the header size in fat_flags.
+ * (and more sects and init locals flags)
+ */
+ fat_flags = 0x03;
+ if (num_exception)
+ fat_flags |= METHOD_HEADER_MORE_SECTS;
+ if (mb->init_locals)
+ fat_flags |= METHOD_HEADER_INIT_LOCALS;
+ fat_header [0] = fat_flags;
+ fat_header [1] = (header_size / 4 ) << 4;
+ short_value = GUINT16_TO_LE (max_stack);
+ memcpy (fat_header + 2, &short_value, 2);
+ int_value = GUINT32_TO_LE (code_size);
+ memcpy (fat_header + 4, &int_value, 4);
+ int_value = GUINT32_TO_LE (local_sig);
+ memcpy (fat_header + 8, &int_value, 4);
+ idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
+ /* add to the fixup todo list */
+ if (mb->ilgen && mb->ilgen->num_token_fixups)
+ mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
+
+ mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
+ if (num_exception) {
+ unsigned char sheader [4];
+ MonoILExceptionInfo * ex_info;
+ MonoILExceptionBlock * ex_block;
+ int j;
+
+ stream_data_align (&assembly->code);
+ /* always use fat format for now */
+ sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
+ num_exception *= 6 * sizeof (guint32);
+ num_exception += 4; /* include the size of the header */
+ sheader [1] = num_exception & 0xff;
+ sheader [2] = (num_exception >> 8) & 0xff;
+ sheader [3] = (num_exception >> 16) & 0xff;
+ mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
+ /* fat header, so we are already aligned */
+ /* reverse order */
+ for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
+ ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
+ if (ex_info->handlers) {
+ int finally_start = ex_info->start + ex_info->len;
+ for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
+ guint32 val;
+ ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
+ /* the flags */
+ val = GUINT32_TO_LE (ex_block->type);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* try offset */
+ val = GUINT32_TO_LE (ex_info->start);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* need fault, too, probably */
+ if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
+ val = GUINT32_TO_LE (finally_start - ex_info->start);
+ else
+ val = GUINT32_TO_LE (ex_info->len);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* handler offset */
+ val = GUINT32_TO_LE (ex_block->start);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* handler len */
+ val = GUINT32_TO_LE (ex_block->len);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ finally_start = ex_block->start + ex_block->len;
+ if (ex_block->extype) {
+ MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
+ return_val_if_nok (error, 0);
+
+ val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
+ } else {
+ if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
+ val = ex_block->filter_offset;
+ else
+ val = 0;
+ }
+ val = GUINT32_TO_LE (val);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
+ clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
+ }
+ } else {
+ g_error ("No clauses for ex info block %d", i);
+ }
+ }
+ }
+ return assembly->text_rva + idx;
+}
+
+/*
+ * Fill in the MethodDef and ParamDef tables for a method.
+ * This is used for both normal methods and constructors.
+ */
+static gboolean
+mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint i, count;
+
+ mono_error_init (error);
+
+ /* room in this table is already allocated */
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ *mb->table_idx = table->next_idx ++;
+ g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
+ values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
+ values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
+ return_val_if_nok (error, FALSE);
+ values [MONO_METHOD_FLAGS] = mb->attrs;
+ values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
+ values [MONO_METHOD_SIGNATURE] = mono_dynimage_encode_method_builder_signature (assembly, mb, error);
+ return_val_if_nok (error, FALSE);
+ values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
+ return_val_if_nok (error, FALSE);
+
+ table = &assembly->tables [MONO_TABLE_PARAM];
+ values [MONO_METHOD_PARAMLIST] = table->next_idx;
+
+ mono_image_add_decl_security (assembly,
+ mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
+
+ if (mb->pinfo) {
+ MonoDynamicTable *mtable;
+ guint32 *mvalues;
+
+ mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
+ mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
+
+ count = 0;
+ for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
+ if (mono_array_get (mb->pinfo, gpointer, i))
+ count++;
+ }
+ table->rows += count;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_PARAM_SIZE;
+ for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
+ MonoReflectionParamBuilder *pb;
+ if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
+ values [MONO_PARAM_FLAGS] = pb->attrs;
+ values [MONO_PARAM_SEQUENCE] = i;
+ if (pb->name != NULL) {
+ values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
+ return_val_if_nok (error, FALSE);
+ } else {
+ values [MONO_PARAM_NAME] = 0;
+ }
+ values += MONO_PARAM_SIZE;
+ if (pb->marshal_info) {
+ mtable->rows++;
+ alloc_table (mtable, mtable->rows);
+ mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
+ mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
+ mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, pb->marshal_info, error);
+ return_val_if_nok (error, FALSE);
+ }
+ pb->table_idx = table->next_idx++;
+ if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
+ guint32 field_type = 0;
+ mtable = &assembly->tables [MONO_TABLE_CONSTANT];
+ mtable->rows ++;
+ alloc_table (mtable, mtable->rows);
+ mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
+ mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
+ mvalues [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
+ mvalues [MONO_CONSTANT_TYPE] = field_type;
+ mvalues [MONO_CONSTANT_PADDING] = 0;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 tok;
+ MonoReflectionMethod *m;
+ int i;
+
+ mono_error_init (error);
+
+ if (!mb->override_methods)
+ return TRUE;
+
+ for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
+ m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
+
+ table = &assembly->tables [MONO_TABLE_METHODIMPL];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_METHODIMPL_SIZE;
+ values [MONO_METHODIMPL_CLASS] = tb->table_idx;
+ values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+
+ tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
+ return_val_if_nok (error, FALSE);
+
+ switch (mono_metadata_token_table (tok)) {
+ case MONO_TABLE_MEMBERREF:
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
+ break;
+ case MONO_TABLE_METHOD:
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ values [MONO_METHODIMPL_DECLARATION] = tok;
+ }
+
+ return TRUE;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static gboolean
+mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ ReflectionMethodBuilder rmb;
+ int i;
+
+ mono_error_init (error);
+
+ if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
+ !mono_image_basic_method (&rmb, assembly, error))
+ return FALSE;
+
+ mb->table_idx = *rmb.table_idx;
+
+ if (mb->dll) { /* It's a P/Invoke method */
+ guint32 moduleref;
+ /* map CharSet values to on-disk values */
+ int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
+ int extra_flags = mb->extra_flags;
+ table = &assembly->tables [MONO_TABLE_IMPLMAP];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_IMPLMAP_SIZE;
+
+ values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
+ values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
+ if (mb->dllentry) {
+ values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
+ return_val_if_nok (error, FALSE);
+ } else {
+ values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
+ return_val_if_nok (error, FALSE);
+ }
+ moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
+ return_val_if_nok (error, FALSE);
+ if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
+ table = &assembly->tables [MONO_TABLE_MODULEREF];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
+ values [MONO_IMPLMAP_SCOPE] = table->rows;
+ }
+ }
+
+ if (mb->generic_params) {
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table->rows += mono_array_length (mb->generic_params);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
+ guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
+
+ mono_image_get_generic_param_info (
+ (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ ReflectionMethodBuilder rmb;
+
+ if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
+ return FALSE;
+
+ if (!mono_image_basic_method (&rmb, assembly, error))
+ return FALSE;
+
+ mb->table_idx = *rmb.table_idx;
+
+ return TRUE;
+}
+#endif
+
+static void
+mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ /* maybe this fixup should be done in the C# code */
+ if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
+ fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ table = &assembly->tables [MONO_TABLE_FIELD];
+ fb->table_idx = table->next_idx ++;
+ g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
+ values = table->values + fb->table_idx * MONO_FIELD_SIZE;
+ values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
+ return_if_nok (error);
+ values [MONO_FIELD_FLAGS] = fb->attrs;
+ values [MONO_FIELD_SIGNATURE] = mono_dynimage_encode_field_signature (assembly, fb, error);
+ return_if_nok (error);
+
+
+ if (fb->offset != -1) {
+ table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
+ values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
+ values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
+ }
+ if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
+ MonoTypeEnum field_type = (MonoTypeEnum)0;
+ table = &assembly->tables [MONO_TABLE_CONSTANT];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_CONSTANT_SIZE;
+ values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
+ values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, fb->def_value, &field_type);
+ values [MONO_CONSTANT_TYPE] = field_type;
+ values [MONO_CONSTANT_PADDING] = 0;
+ }
+ if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
+ guint32 rva_idx;
+ table = &assembly->tables [MONO_TABLE_FIELDRVA];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
+ values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
+ /*
+ * We store it in the code section because it's simpler for now.
+ */
+ if (fb->rva_data) {
+ if (mono_array_length (fb->rva_data) >= 10)
+ stream_data_align (&assembly->code);
+ rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
+ } else
+ rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
+ values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
+ }
+ if (fb->marshal_info) {
+ table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
+ values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
+ values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, fb->marshal_info, error);
+ return_if_nok (error);
+ }
+}
+
+static void
+mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint num_methods = 0;
+ guint32 semaidx;
+
+ /*
+ * we need to set things in the following tables:
+ * PROPERTYMAP (info already filled in _get_type_info ())
+ * PROPERTY (rows already preallocated in _get_type_info ())
+ * METHOD (method info already done with the generic method code)
+ * METHODSEMANTICS
+ * CONSTANT
+ */
+ table = &assembly->tables [MONO_TABLE_PROPERTY];
+ pb->table_idx = table->next_idx ++;
+ values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
+ values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
+ return_if_nok (error);
+ values [MONO_PROPERTY_FLAGS] = pb->attrs;
+ values [MONO_PROPERTY_TYPE] = mono_dynimage_save_encode_property_signature (assembly, pb, error);
+ return_if_nok (error);
+
+
+ /* FIXME: we still don't handle 'other' methods */
+ if (pb->get_method) num_methods ++;
+ if (pb->set_method) num_methods ++;
+
+ table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
+ table->rows += num_methods;
+ alloc_table (table, table->rows);
+
+ if (pb->get_method) {
+ semaidx = table->next_idx ++;
+ values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
+ values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
+ values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
+ }
+ if (pb->set_method) {
+ semaidx = table->next_idx ++;
+ values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
+ values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
+ values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
+ }
+ if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
+ MonoTypeEnum field_type = (MonoTypeEnum)0;
+ table = &assembly->tables [MONO_TABLE_CONSTANT];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_CONSTANT_SIZE;
+ values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
+ values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
+ values [MONO_CONSTANT_TYPE] = field_type;
+ values [MONO_CONSTANT_PADDING] = 0;
+ }
+}
+
+static void
+mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint num_methods = 0;
+ guint32 semaidx;
+
+ /*
+ * we need to set things in the following tables:
+ * EVENTMAP (info already filled in _get_type_info ())
+ * EVENT (rows already preallocated in _get_type_info ())
+ * METHOD (method info already done with the generic method code)
+ * METHODSEMANTICS
+ */
+ table = &assembly->tables [MONO_TABLE_EVENT];
+ eb->table_idx = table->next_idx ++;
+ values = table->values + eb->table_idx * MONO_EVENT_SIZE;
+ values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
+ return_if_nok (error);
+ values [MONO_EVENT_FLAGS] = eb->attrs;
+ MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
+ return_if_nok (error);
+ values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
+
+ /*
+ * FIXME: we still don't handle 'other' methods
+ */
+ if (eb->add_method) num_methods ++;
+ if (eb->remove_method) num_methods ++;
+ if (eb->raise_method) num_methods ++;
+
+ table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
+ table->rows += num_methods;
+ alloc_table (table, table->rows);
+
+ if (eb->add_method) {
+ semaidx = table->next_idx ++;
+ values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
+ values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
+ values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ }
+ if (eb->remove_method) {
+ semaidx = table->next_idx ++;
+ values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
+ values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
+ values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ }
+ if (eb->raise_method) {
+ semaidx = table->next_idx ++;
+ values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
+ values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
+ values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ }
+}
+
+static void
+encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ MonoDynamicTable *table;
+ guint32 num_constraints, i;
+ guint32 *values;
+ guint32 table_idx;
+
+ table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
+ num_constraints = gparam->iface_constraints ?
+ mono_array_length (gparam->iface_constraints) : 0;
+ table->rows += num_constraints;
+ if (gparam->base_type)
+ table->rows++;
+ alloc_table (table, table->rows);
+
+ if (gparam->base_type) {
+ table_idx = table->next_idx ++;
+ values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
+
+ MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
+ return_if_nok (error);
+ values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
+ values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
+ }
+
+ for (i = 0; i < num_constraints; i++) {
+ MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
+ gparam->iface_constraints, gpointer, i);
+
+ table_idx = table->next_idx ++;
+ values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
+
+ MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
+ return_if_nok (error);
+
+ values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
+ values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
+ }
+}
+
+static void
+mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ GenericParamTableEntry *entry;
+
+ /*
+ * The GenericParam table must be sorted according to the `owner' field.
+ * We need to do this sorting prior to writing the GenericParamConstraint
+ * table, since we have to use the final GenericParam table indices there
+ * and they must also be sorted.
+ */
+
+ entry = g_new0 (GenericParamTableEntry, 1);
+ entry->owner = owner;
+ /* FIXME: track where gen_params should be freed and remove the GC root as well */
+ MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
+ entry->gparam = gparam;
+
+ g_ptr_array_add (assembly->gen_params, entry);
+}
+
+static gboolean
+write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ MonoGenericParam *param;
+ guint32 *values;
+ guint32 table_idx;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table_idx = table->next_idx ++;
+ values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
+
+ MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
+ return_val_if_nok (error, FALSE);
+
+ param = gparam_type->data.generic_param;
+
+ values [MONO_GENERICPARAM_OWNER] = entry->owner;
+ values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
+ values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
+ values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
+
+ if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
+ return FALSE;
+
+ encode_constraints (entry->gparam, table_idx, assembly, error);
+ return_val_if_nok (error, FALSE);
+
+ return TRUE;
+}
+
+static void
+collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
+{
+ int i;
+
+ mono_ptr_array_append (*types, type);
+
+ if (!type->subtypes)
+ return;
+
+ for (i = 0; i < mono_array_length (type->subtypes); ++i) {
+ MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
+ collect_types (types, subtype);
+ }
+}
+
+static gint
+compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
+{
+ if ((*type1)->table_idx < (*type2)->table_idx)
+ return -1;
+ else
+ if ((*type1)->table_idx > (*type2)->table_idx)
+ return 1;
+ else
+ return 0;
+}
+
+static gboolean
+params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
+ int i;
+
+ mono_error_init (error);
+ if (!pinfo)
+ return TRUE;
+ for (i = 0; i < mono_array_length (pinfo); ++i) {
+ MonoReflectionParamBuilder *pb;
+ pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
+ if (!pb)
+ continue;
+ if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
+ int i;
+
+ mono_error_init (error);
+
+ if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
+ return FALSE;
+ if (tb->fields) {
+ for (i = 0; i < tb->num_fields; ++i) {
+ MonoReflectionFieldBuilder* fb;
+ fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
+ return FALSE;
+ }
+ }
+ if (tb->events) {
+ for (i = 0; i < mono_array_length (tb->events); ++i) {
+ MonoReflectionEventBuilder* eb;
+ eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
+ return FALSE;
+ }
+ }
+ if (tb->properties) {
+ for (i = 0; i < mono_array_length (tb->properties); ++i) {
+ MonoReflectionPropertyBuilder* pb;
+ pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
+ return FALSE;
+ }
+ }
+ if (tb->ctors) {
+ for (i = 0; i < mono_array_length (tb->ctors); ++i) {
+ MonoReflectionCtorBuilder* cb;
+ cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
+ !params_add_cattrs (assembly, cb->pinfo, error))
+ return FALSE;
+ }
+ }
+
+ if (tb->methods) {
+ for (i = 0; i < tb->num_methods; ++i) {
+ MonoReflectionMethodBuilder* mb;
+ mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
+ !params_add_cattrs (assembly, mb->pinfo, error))
+ return FALSE;
+ }
+ }
+
+ if (tb->subtypes) {
+ for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
+ if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
+{
+ int i;
+
+ mono_error_init (error);
+
+ if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
+ return FALSE;
+
+ if (moduleb->global_methods) {
+ for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
+ MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
+ !params_add_cattrs (assembly, mb->pinfo, error))
+ return FALSE;
+ }
+ }
+
+ if (moduleb->global_fields) {
+ for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
+ MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
+ if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
+ return FALSE;
+ }
+ }
+
+ if (moduleb->types) {
+ for (i = 0; i < moduleb->num_types; ++i) {
+ if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ char blob_size [6];
+ guchar hash [20];
+ char *b = blob_size;
+ char *dir, *path;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_FILE];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_FILE_SIZE;
+ values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
+ values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
+ if (image_is_dynamic (module->image)) {
+ /* This depends on the fact that the main module is emitted last */
+ dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
+ return_val_if_nok (error, FALSE);
+ path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
+ } else {
+ dir = NULL;
+ path = g_strdup (module->image->name);
+ }
+ mono_sha1_get_digest_from_file (path, hash);
+ g_free (dir);
+ g_free (path);
+ mono_metadata_encode_value (20, b, &b);
+ values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
+ table->next_idx ++;
+ return TRUE;
+}
+
+static void
+mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MonoDynamicTable *table;
+ int i;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_MODULE];
+ mb->table_idx = table->next_idx ++;
+ table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
+ return_if_nok (error);
+ i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
+ i /= 16;
+ ++i;
+ table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
+ table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
+ table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
+ table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
+}
+
+static guint32
+mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
+ guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 visib, res;
+
+ visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
+ return 0;
+
+ table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
+
+ values [MONO_EXP_TYPE_FLAGS] = klass->flags;
+ values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
+ if (klass->nested_in)
+ values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
+ else
+ values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
+ values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+ values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+
+ res = table->next_idx;
+
+ table->next_idx ++;
+
+ /* Emit nested types */
+ if (klass->ext && klass->ext->nested_classes) {
+ GList *tmp;
+
+ for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
+ mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
+ }
+
+ return res;
+}
+
+static void
+mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
+ guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
+ MonoError *error)
+{
+ MonoClass *klass;
+ guint32 idx, i;
+
+ mono_error_init (error);
+
+ MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+ return_if_nok (error);
+
+ klass = mono_class_from_mono_type (t);
+
+ klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
+
+ idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
+ parent_index, assembly);
+
+ /*
+ * Emit nested types
+ * We need to do this ourselves since klass->nested_classes is not set up.
+ */
+ if (tb->subtypes) {
+ for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
+ mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
+ return_if_nok (error);
+ }
+ }
+}
+
+static void
+mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
+ guint32 module_index, MonoDynamicImage *assembly)
+{
+ MonoImage *image = module->image;
+ MonoTableInfo *t;
+ guint32 i;
+
+ t = &image->tables [MONO_TABLE_TYPEDEF];
+
+ for (i = 0; i < t->rows; ++i) {
+ MonoError error;
+ MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
+ if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
+ mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
+ }
+}
+
+static void
+add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 scope, scope_idx, impl, current_idx;
+ gboolean forwarder = TRUE;
+ gpointer iter = NULL;
+ MonoClass *nested;
+
+ if (klass->nested_in) {
+ impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
+ forwarder = FALSE;
+ } else {
+ scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
+ g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
+ scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
+ impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
+ }
+
+ table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
+
+ table->rows++;
+ alloc_table (table, table->rows);
+ current_idx = table->next_idx;
+ values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
+
+ values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
+ values [MONO_EXP_TYPE_TYPEDEF] = 0;
+ values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
+ values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+ values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+
+ table->next_idx++;
+
+ while ((nested = mono_class_get_nested_types (klass, &iter)))
+ add_exported_type (assemblyb, assembly, nested, current_idx);
+}
+
+static void
+mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
+{
+ MonoError error;
+ MonoClass *klass;
+ int i;
+
+ if (!assemblyb->type_forwarders)
+ return;
+
+ for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
+ MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
+ MonoType *type;
+ if (!t)
+ continue;
+
+ type = mono_reflection_type_get_handle (t, &error);
+ mono_error_assert_ok (&error);
+ g_assert (type);
+
+ klass = mono_class_from_mono_type (type);
+
+ add_exported_type (assemblyb, assembly, klass, 0);
+ }
+}
+
+#define align_pointer(base,p)\
+ do {\
+ guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
+ if (__diff & 3)\
+ (p) += 4 - (__diff & 3);\
+ } while (0)
+
+static int
+compare_constants (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+ return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
+}
+
+static int
+compare_semantics (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+ int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
+ if (assoc)
+ return assoc;
+ return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
+}
+
+static int
+compare_custom_attrs (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+
+ return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
+}
+
+static int
+compare_field_marshal (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+
+ return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
+}
+
+static int
+compare_nested (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+
+ return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
+}
+
+static int
+compare_genericparam (const void *a, const void *b)
+{
+ MonoError error;
+ const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
+ const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
+
+ if ((*b_entry)->owner == (*a_entry)->owner) {
+ MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
+ mono_error_assert_ok (&error);
+ MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
+ mono_error_assert_ok (&error);
+ return
+ mono_type_get_generic_param_num (a_type) -
+ mono_type_get_generic_param_num (b_type);
+ } else
+ return (*a_entry)->owner - (*b_entry)->owner;
+}
+
+static int
+compare_declsecurity_attrs (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+
+ return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
+}
+
+static int
+compare_interface_impl (const void *a, const void *b)
+{
+ const guint32 *a_values = (const guint32 *)a;
+ const guint32 *b_values = (const guint32 *)b;
+
+ int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
+ if (klass)
+ return klass;
+
+ return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
+}
+
+struct StreamDesc {
+ const char *name;
+ MonoDynamicStream *stream;
+};
+
+/*
+ * build_compressed_metadata() fills in the blob of data that represents the
+ * raw metadata as it will be saved in the PE file. The five streams are output
+ * and the metadata tables are comnpressed from the guint32 array representation,
+ * to the compressed on-disk format.
+ */
+static gboolean
+build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
+{
+ MonoDynamicTable *table;
+ int i;
+ guint64 valid_mask = 0;
+ guint64 sorted_mask;
+ guint32 heapt_size = 0;
+ guint32 meta_size = 256; /* allow for header and other stuff */
+ guint32 table_offset;
+ guint32 ntables = 0;
+ guint64 *int64val;
+ guint32 *int32val;
+ guint16 *int16val;
+ MonoImage *meta;
+ unsigned char *p;
+ struct StreamDesc stream_desc [5];
+
+ mono_error_init (error);
+
+ qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
+ for (i = 0; i < assembly->gen_params->len; i++) {
+ GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
+ if (!write_generic_param_entry (assembly, entry, error))
+ return FALSE;
+ }
+
+ stream_desc [0].name = "#~";
+ stream_desc [0].stream = &assembly->tstream;
+ stream_desc [1].name = "#Strings";
+ stream_desc [1].stream = &assembly->sheap;
+ stream_desc [2].name = "#US";
+ stream_desc [2].stream = &assembly->us;
+ stream_desc [3].name = "#Blob";
+ stream_desc [3].stream = &assembly->blob;
+ stream_desc [4].name = "#GUID";
+ stream_desc [4].stream = &assembly->guid;
+
+ /* tables that are sorted */
+ sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
+ | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
+ | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
+ | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
+ | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
+ | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
+ | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
+
+ /* Compute table sizes */
+ /* the MonoImage has already been created in mono_reflection_dynimage_basic_init() */
+ meta = &assembly->image;
+
+ /* sizes should be multiple of 4 */
+ mono_dynstream_data_align (&assembly->blob);
+ mono_dynstream_data_align (&assembly->guid);
+ mono_dynstream_data_align (&assembly->sheap);
+ mono_dynstream_data_align (&assembly->us);
+
+ /* Setup the info used by compute_sizes () */
+ meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
+ meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
+ meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
+
+ meta_size += assembly->blob.index;
+ meta_size += assembly->guid.index;
+ meta_size += assembly->sheap.index;
+ meta_size += assembly->us.index;
+
+ for (i=0; i < MONO_TABLE_NUM; ++i)
+ meta->tables [i].rows = assembly->tables [i].rows;
+
+ for (i = 0; i < MONO_TABLE_NUM; i++){
+ if (meta->tables [i].rows == 0)
+ continue;
+ valid_mask |= (guint64)1 << i;
+ ntables ++;
+ meta->tables [i].row_size = mono_metadata_compute_size (
+ meta, i, &meta->tables [i].size_bitfield);
+ heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
+ }
+ heapt_size += 24; /* #~ header size */
+ heapt_size += ntables * 4;
+ /* make multiple of 4 */
+ heapt_size += 3;
+ heapt_size &= ~3;
+ meta_size += heapt_size;
+ meta->raw_metadata = (char *)g_malloc0 (meta_size);
+ p = (unsigned char*)meta->raw_metadata;
+ /* the metadata signature */
+ *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
+ /* version numbers and 4 bytes reserved */
+ int16val = (guint16*)p;
+ *int16val++ = GUINT16_TO_LE (meta->md_version_major);
+ *int16val = GUINT16_TO_LE (meta->md_version_minor);
+ p += 8;
+ /* version string */
+ int32val = (guint32*)p;
+ *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
+ p += 4;
+ memcpy (p, meta->version, strlen (meta->version));
+ p += GUINT32_FROM_LE (*int32val);
+ align_pointer (meta->raw_metadata, p);
+ int16val = (guint16*)p;
+ *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
+ *int16val = GUINT16_TO_LE (5); /* number of streams */
+ p += 4;
+
+ /*
+ * write the stream info.
+ */
+ table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
+ table_offset += 3; table_offset &= ~3;
+
+ assembly->tstream.index = heapt_size;
+ for (i = 0; i < 5; ++i) {
+ int32val = (guint32*)p;
+ stream_desc [i].stream->offset = table_offset;
+ *int32val++ = GUINT32_TO_LE (table_offset);
+ *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
+ table_offset += GUINT32_FROM_LE (*int32val);
+ table_offset += 3; table_offset &= ~3;
+ p += 8;
+ strcpy ((char*)p, stream_desc [i].name);
+ p += strlen (stream_desc [i].name) + 1;
+ align_pointer (meta->raw_metadata, p);
+ }
+ /*
+ * now copy the data, the table stream header and contents goes first.
+ */
+ g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
+ p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
+ int32val = (guint32*)p;
+ *int32val = GUINT32_TO_LE (0); /* reserved */
+ p += 4;
+
+ *p++ = 2; /* version */
+ *p++ = 0;
+
+ if (meta->idx_string_wide)
+ *p |= 0x01;
+ if (meta->idx_guid_wide)
+ *p |= 0x02;
+ if (meta->idx_blob_wide)
+ *p |= 0x04;
+ ++p;
+ *p++ = 1; /* reserved */
+ int64val = (guint64*)p;
+ *int64val++ = GUINT64_TO_LE (valid_mask);
+ *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
+ p += 16;
+ int32val = (guint32*)p;
+ for (i = 0; i < MONO_TABLE_NUM; i++){
+ if (meta->tables [i].rows == 0)
+ continue;
+ *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
+ }
+ p = (unsigned char*)int32val;
+
+ /* sort the tables that still need sorting */
+ table = &assembly->tables [MONO_TABLE_CONSTANT];
+ if (table->rows)
+ qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
+ table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
+ if (table->rows)
+ qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
+ table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+ if (table->rows)
+ qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
+ table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
+ if (table->rows)
+ qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
+ table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
+ if (table->rows)
+ qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
+ /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
+ table = &assembly->tables [MONO_TABLE_DECLSECURITY];
+ if (table->rows)
+ qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
+ table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
+ if (table->rows)
+ qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
+
+ /* compress the tables */
+ for (i = 0; i < MONO_TABLE_NUM; i++){
+ int row, col;
+ guint32 *values;
+ guint32 bitfield = meta->tables [i].size_bitfield;
+ if (!meta->tables [i].rows)
+ continue;
+ if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
+ g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
+ meta->tables [i].base = (char*)p;
+ for (row = 1; row <= meta->tables [i].rows; ++row) {
+ values = assembly->tables [i].values + row * assembly->tables [i].columns;
+ for (col = 0; col < assembly->tables [i].columns; ++col) {
+ switch (mono_metadata_table_size (bitfield, col)) {
+ case 1:
+ *p++ = values [col];
+ break;
+ case 2:
+ *p++ = values [col] & 0xff;
+ *p++ = (values [col] >> 8) & 0xff;
+ break;
+ case 4:
+ *p++ = values [col] & 0xff;
+ *p++ = (values [col] >> 8) & 0xff;
+ *p++ = (values [col] >> 16) & 0xff;
+ *p++ = (values [col] >> 24) & 0xff;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ }
+ g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
+ }
+
+ g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
+ memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
+ memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
+ memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
+ memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
+
+ assembly->meta_size = assembly->guid.offset + assembly->guid.index;
+
+ return TRUE;
+}
+
+/*
+ * Some tables in metadata need to be sorted according to some criteria, but
+ * when methods and fields are first created with reflection, they may be assigned a token
+ * that doesn't correspond to the final token they will get assigned after the sorting.
+ * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
+ * with the reflection objects that represent them. Once all the tables are set up, the
+ * reflection objects will contains the correct table index. fixup_method() will fixup the
+ * tokens for the method with ILGenerator @ilgen.
+ */
+static void
+fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
+{
+ guint32 code_idx = GPOINTER_TO_UINT (value);
+ MonoReflectionILTokenInfo *iltoken;
+ MonoReflectionFieldBuilder *field;
+ MonoReflectionCtorBuilder *ctor;
+ MonoReflectionMethodBuilder *method;
+ MonoReflectionTypeBuilder *tb;
+ MonoReflectionArrayMethod *am;
+ guint32 i, idx = 0;
+ unsigned char *target;
+
+ for (i = 0; i < ilgen->num_token_fixups; ++i) {
+ iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
+ target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
+ switch (target [3]) {
+ case MONO_TABLE_FIELD:
+ if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
+ field = (MonoReflectionFieldBuilder *)iltoken->member;
+ idx = field->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
+ MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
+ idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ case MONO_TABLE_METHOD:
+ if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
+ method = (MonoReflectionMethodBuilder *)iltoken->member;
+ idx = method->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
+ ctor = (MonoReflectionCtorBuilder *)iltoken->member;
+ idx = ctor->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ case MONO_TABLE_TYPEDEF:
+ if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
+ g_assert_not_reached ();
+ tb = (MonoReflectionTypeBuilder *)iltoken->member;
+ idx = tb->table_idx;
+ break;
+ case MONO_TABLE_MEMBERREF:
+ if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
+ am = (MonoReflectionArrayMethod*)iltoken->member;
+ idx = am->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ g_assert (m->klass->generic_class || m->klass->generic_container);
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
+ !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
+ continue;
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ case MONO_TABLE_METHODSPEC:
+ if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ g_assert (mono_method_signature (m)->generic_param_count);
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
+ continue;
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ default:
+ g_error ("got unexpected table 0x%02x in fixup", target [3]);
+ }
+ target [0] = idx & 0xff;
+ target [1] = (idx >> 8) & 0xff;
+ target [2] = (idx >> 16) & 0xff;
+ }
+}
+
+/*
+ * fixup_cattrs:
+ *
+ * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
+ * value is not known when the table is emitted.
+ */
+static void
+fixup_cattrs (MonoDynamicImage *assembly)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 type, i, idx, token;
+ MonoObject *ctor;
+
+ table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+
+ for (i = 0; i < table->rows; ++i) {
+ values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
+
+ type = values [MONO_CUSTOM_ATTR_TYPE];
+ if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
+ idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
+ token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
+ ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
+ g_assert (ctor);
+
+ if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
+ idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
+ values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+ } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
+ MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
+ idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
+ values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+ }
+ }
+ }
+}
+
+static gboolean
+assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
+ values [MONO_MANIFEST_OFFSET] = rsrc->offset;
+ values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
+ values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
+ return_val_if_nok (error, FALSE);
+ values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
+ table->next_idx++;
+ return TRUE;
+}
+
+static gboolean
+assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ char blob_size [6];
+ guchar hash [20];
+ char *b = blob_size;
+ char *name, *sname;
+ guint32 idx, offset;
+
+ mono_error_init (error);
+
+ if (rsrc->filename) {
+ name = mono_string_to_utf8_checked (rsrc->filename, error);
+ return_val_if_nok (error, FALSE);
+ sname = g_path_get_basename (name);
+
+ table = &assembly->tables [MONO_TABLE_FILE];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_FILE_SIZE;
+ values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
+ values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
+ g_free (sname);
+
+ mono_sha1_get_digest_from_file (name, hash);
+ mono_metadata_encode_value (20, b, &b);
+ values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
+ g_free (name);
+ idx = table->next_idx++;
+ rsrc->offset = 0;
+ idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
+ } else {
+ char sizebuf [4];
+ char *data;
+ guint len;
+ if (rsrc->data) {
+ data = mono_array_addr (rsrc->data, char, 0);
+ len = mono_array_length (rsrc->data);
+ } else {
+ data = NULL;
+ len = 0;
+ }
+ offset = len;
+ sizebuf [0] = offset; sizebuf [1] = offset >> 8;
+ sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
+ rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
+ mono_image_add_stream_data (&assembly->resources, data, len);
+
+ if (!mb->is_main)
+ /*
+ * The entry should be emitted into the MANIFESTRESOURCE table of
+ * the main module, but that needs to reference the FILE table
+ * which isn't emitted yet.
+ */
+ return TRUE;
+ else
+ idx = 0;
+ }
+
+ return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
+}
+
+static gboolean
+set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
+{
+ gchar *ver, *p, *str;
+ guint32 i;
+
+ mono_error_init (error);
+
+ values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
+ values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
+ values [MONO_ASSEMBLY_REV_NUMBER] = 0;
+ values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
+ if (!version)
+ return TRUE;
+ ver = str = mono_string_to_utf8_checked (version, error);
+ return_val_if_nok (error, FALSE);
+ for (i = 0; i < 4; ++i) {
+ values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
+ switch (*p) {
+ case '.':
+ p++;
+ break;
+ case '*':
+ /* handle Revision and Build */
+ p++;
+ break;
+ }
+ ver = p;
+ }
+ g_free (str);
+ return TRUE;
+}
+
+static guint32
+load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
+ gsize len;
+ guint32 token = 0;
+ char blob_size [6];
+ char *b = blob_size;
+
+ if (!pkey)
+ return token;
+
+ len = mono_array_length (pkey);
+ mono_metadata_encode_value (len, b, &b);
+ token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
+ mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
+
+ assembly->public_key = (guint8 *)g_malloc (len);
+ memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
+ assembly->public_key_len = len;
+
+ /* Special case: check for ECMA key (16 bytes) */
+ if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
+ /* In this case we must reserve 128 bytes (1024 bits) for the signature */
+ assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
+ } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
+ /* minimum key size (in 2.0) is 384 bits */
+ assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
+ } else {
+ /* FIXME - verifier */
+ g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
+ assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
+ }
+ assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
+
+ return token;
+}
+
+static gboolean
+mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
+{
+ MonoDynamicTable *table;
+ MonoDynamicImage *assembly;
+ MonoReflectionAssemblyBuilder *assemblyb;
+ MonoDomain *domain;
+ guint32 *values;
+ int i;
+ guint32 module_index;
+
+ mono_error_init (error);
+
+ assemblyb = moduleb->assemblyb;
+ assembly = moduleb->dynamic_image;
+ domain = mono_object_domain (assemblyb);
+
+ /* Emit ASSEMBLY table */
+ table = &assembly->tables [MONO_TABLE_ASSEMBLY];
+ alloc_table (table, 1);
+ values = table->values + MONO_ASSEMBLY_SIZE;
+ values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
+ values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
+ return_val_if_nok (error, FALSE);
+ if (assemblyb->culture) {
+ values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
+ return_val_if_nok (error, FALSE);
+ } else {
+ values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
+ }
+ values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
+ values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
+ if (!set_version_from_string (assemblyb->version, values, error))
+ return FALSE;
+
+ /* Emit FILE + EXPORTED_TYPE table */
+ module_index = 0;
+ for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
+ int j;
+ MonoReflectionModuleBuilder *file_module =
+ mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+ if (file_module != moduleb) {
+ if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
+ return FALSE;
+ module_index ++;
+ if (file_module->types) {
+ for (j = 0; j < file_module->num_types; ++j) {
+ MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
+ mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
+ return_val_if_nok (error, FALSE);
+ }
+ }
+ }
+ }
+ if (assemblyb->loaded_modules) {
+ for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
+ MonoReflectionModule *file_module =
+ mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
+ if (!mono_image_fill_file_table (domain, file_module, assembly, error))
+ return FALSE;
+ module_index ++;
+ mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
+ }
+ }
+ if (assemblyb->type_forwarders)
+ mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
+
+ /* Emit MANIFESTRESOURCE table */
+ module_index = 0;
+ for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
+ int j;
+ MonoReflectionModuleBuilder *file_module =
+ mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+ /* The table for the main module is emitted later */
+ if (file_module != moduleb) {
+ module_index ++;
+ if (file_module->resources) {
+ int len = mono_array_length (file_module->resources);
+ for (j = 0; j < len; ++j) {
+ MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
+ if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT_SAVE
+
+/*
+ * Insert into the metadata tables all the info about the TypeBuilder tb.
+ * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
+ */
+static gboolean
+mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
+{
+ MonoDynamicTable *table;
+ guint *values;
+ int i, is_object = 0, is_system = 0;
+ char *n;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
+ values [MONO_TYPEDEF_FLAGS] = tb->attrs;
+ n = mono_string_to_utf8_checked (tb->name, error);
+ return_val_if_nok (error, FALSE);
+ if (strcmp (n, "Object") == 0)
+ is_object++;
+ values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
+ g_free (n);
+ n = mono_string_to_utf8_checked (tb->nspace, error);
+ return_val_if_nok (error, FALSE);
+ if (strcmp (n, "System") == 0)
+ is_system++;
+ values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
+ g_free (n);
+ if (tb->parent && !(is_system && is_object) &&
+ !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
+ MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
+ return_val_if_nok (error, FALSE);
+ values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
+ } else {
+ values [MONO_TYPEDEF_EXTENDS] = 0;
+ }
+ values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
+ values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
+
+ /*
+ * if we have explicitlayout or sequentiallayouts, output data in the
+ * ClassLayout table.
+ */
+ if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
+ ((tb->class_size > 0) || (tb->packing_size > 0))) {
+ table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
+ values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
+ values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
+ values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
+ }
+
+ /* handle interfaces */
+ if (tb->interfaces) {
+ table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
+ i = table->rows;
+ table->rows += mono_array_length (tb->interfaces);
+ alloc_table (table, table->rows);
+ values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
+ for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
+ MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
+ MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
+ return_val_if_nok (error, FALSE);
+ values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
+ values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
+ values += MONO_INTERFACEIMPL_SIZE;
+ }
+ }
+
+ /* handle fields */
+ if (tb->fields) {
+ table = &assembly->tables [MONO_TABLE_FIELD];
+ table->rows += tb->num_fields;
+ alloc_table (table, table->rows);
+ for (i = 0; i < tb->num_fields; ++i) {
+ mono_image_get_field_info (
+ mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
+ return_val_if_nok (error, FALSE);
+ }
+ }
+
+ /* handle constructors */
+ if (tb->ctors) {
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ table->rows += mono_array_length (tb->ctors);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (tb->ctors); ++i) {
+ if (!mono_image_get_ctor_info (domain,
+ mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
+ assembly, error))
+ return FALSE;
+ }
+ }
+
+ /* handle methods */
+ if (tb->methods) {
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ table->rows += tb->num_methods;
+ alloc_table (table, table->rows);
+ for (i = 0; i < tb->num_methods; ++i) {
+ if (!mono_image_get_method_info (
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
+ return FALSE;
+ }
+ }
+
+ /* Do the same with properties etc.. */
+ if (tb->events && mono_array_length (tb->events)) {
+ table = &assembly->tables [MONO_TABLE_EVENT];
+ table->rows += mono_array_length (tb->events);
+ alloc_table (table, table->rows);
+ table = &assembly->tables [MONO_TABLE_EVENTMAP];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
+ values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
+ values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
+ for (i = 0; i < mono_array_length (tb->events); ++i) {
+ mono_image_get_event_info (
+ mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
+ return_val_if_nok (error, FALSE);
+ }
+ }
+ if (tb->properties && mono_array_length (tb->properties)) {
+ table = &assembly->tables [MONO_TABLE_PROPERTY];
+ table->rows += mono_array_length (tb->properties);
+ alloc_table (table, table->rows);
+ table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
+ values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
+ values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
+ for (i = 0; i < mono_array_length (tb->properties); ++i) {
+ mono_image_get_property_info (
+ mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
+ return_val_if_nok (error, FALSE);
+ }
+ }
+
+ /* handle generic parameters */
+ if (tb->generic_params) {
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table->rows += mono_array_length (tb->generic_params);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
+ guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
+
+ mono_image_get_generic_param_info (
+ mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
+ }
+ }
+
+ mono_image_add_decl_security (assembly,
+ mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
+
+ if (tb->subtypes) {
+ MonoDynamicTable *ntable;
+
+ ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
+ ntable->rows += mono_array_length (tb->subtypes);
+ alloc_table (ntable, ntable->rows);
+ values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
+
+ for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
+ MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
+
+ values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
+ values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
+ /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
+ mono_string_to_utf8 (subtype->name), subtype->table_idx,
+ mono_string_to_utf8 (tb->name), tb->table_idx,
+ ntable->next_idx, ntable->rows);*/
+ values += MONO_NESTED_CLASS_SIZE;
+ ntable->next_idx++;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * mono_image_build_metadata() will fill the info in all the needed metadata tables
+ * for the modulebuilder @moduleb.
+ * At the end of the process, method and field tokens are fixed up and the
+ * on-disk compressed metadata representation is created.
+ * Return TRUE on success, or FALSE on failure and sets @error
+ */
+gboolean
+mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
+{
+ MonoDynamicTable *table;
+ MonoDynamicImage *assembly;
+ MonoReflectionAssemblyBuilder *assemblyb;
+ MonoDomain *domain;
+ MonoPtrArray types;
+ guint32 *values;
+ int i, j;
+
+ mono_error_init (error);
+
+ assemblyb = moduleb->assemblyb;
+ assembly = moduleb->dynamic_image;
+ domain = mono_object_domain (assemblyb);
+
+ if (assembly->text_rva)
+ return TRUE;
+
+ assembly->text_rva = START_TEXT_RVA;
+
+ if (moduleb->is_main) {
+ mono_image_emit_manifest (moduleb, error);
+ return_val_if_nok (error, FALSE);
+ }
+
+ table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ table->rows = 1; /* .<Module> */
+ table->next_idx++;
+ alloc_table (table, table->rows);
+ /*
+ * Set the first entry.
+ */
+ values = table->values + table->columns;
+ values [MONO_TYPEDEF_FLAGS] = 0;
+ values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
+ values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
+ values [MONO_TYPEDEF_EXTENDS] = 0;
+ values [MONO_TYPEDEF_FIELD_LIST] = 1;
+ values [MONO_TYPEDEF_METHOD_LIST] = 1;
+
+ /*
+ * handle global methods
+ * FIXME: test what to do when global methods are defined in multiple modules.
+ */
+ if (moduleb->global_methods) {
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ table->rows += mono_array_length (moduleb->global_methods);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
+ if (!mono_image_get_method_info (
+ mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
+ goto leave;
+ }
+ }
+ if (moduleb->global_fields) {
+ table = &assembly->tables [MONO_TABLE_FIELD];
+ table->rows += mono_array_length (moduleb->global_fields);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
+ mono_image_get_field_info (
+ mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
+ error);
+ if (!is_ok (error))
+ goto leave;
+ }
+ }
+
+ table = &assembly->tables [MONO_TABLE_MODULE];
+ alloc_table (table, 1);
+ mono_image_fill_module_table (domain, moduleb, assembly, error);
+ if (!is_ok (error))
+ goto leave;
+
+ /* Collect all types into a list sorted by their table_idx */
+ mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
+
+ if (moduleb->types)
+ for (i = 0; i < moduleb->num_types; ++i) {
+ MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
+ collect_types (&types, type);
+ }
+
+ mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
+ table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ table->rows += mono_ptr_array_size (types);
+ alloc_table (table, table->rows);
+
+ /*
+ * Emit type names + namespaces at one place inside the string heap,
+ * so load_class_names () needs to touch fewer pages.
+ */
+ for (i = 0; i < mono_ptr_array_size (types); ++i) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
+ string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
+ if (!is_ok (error))
+ goto leave_types;
+ }
+ for (i = 0; i < mono_ptr_array_size (types); ++i) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
+ string_heap_insert_mstring (&assembly->sheap, tb->name, error);
+ if (!is_ok (error))
+ goto leave_types;
+ }
+
+ for (i = 0; i < mono_ptr_array_size (types); ++i) {
+ MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
+ if (!mono_image_get_type_info (domain, type, assembly, error))
+ goto leave_types;
+ }
+
+ /*
+ * table->rows is already set above and in mono_image_fill_module_table.
+ */
+ /* add all the custom attributes at the end, once all the indexes are stable */
+ if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
+ goto leave_types;
+
+ /* CAS assembly permissions */
+ if (assemblyb->permissions_minimum)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
+ if (assemblyb->permissions_optional)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
+ if (assemblyb->permissions_refused)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
+
+ if (!module_add_cattrs (assembly, moduleb, error))
+ goto leave_types;
+
+ /* fixup tokens */
+ mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
+
+ /* Create the MethodImpl table. We do this after emitting all methods so we already know
+ * the final tokens and don't need another fixup pass. */
+
+ if (moduleb->global_methods) {
+ for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
+ MonoReflectionMethodBuilder *mb = mono_array_get (
+ moduleb->global_methods, MonoReflectionMethodBuilder*, i);
+ if (!mono_image_add_methodimpl (assembly, mb, error))
+ goto leave_types;
+ }
+ }
+
+ for (i = 0; i < mono_ptr_array_size (types); ++i) {
+ MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
+ if (type->methods) {
+ for (j = 0; j < type->num_methods; ++j) {
+ MonoReflectionMethodBuilder *mb = mono_array_get (
+ type->methods, MonoReflectionMethodBuilder*, j);
+
+ if (!mono_image_add_methodimpl (assembly, mb, error))
+ goto leave_types;
+ }
+ }
+ }
+
+ fixup_cattrs (assembly);
+
+leave_types:
+ mono_ptr_array_destroy (types);
+leave:
+
+ return mono_error_ok (error);
+}
+
+#else /* DISABLE_REFLECTION_EMIT_SAVE */
+
+gboolean
+mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
+{
+ g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
+}
+
+#endif /* DISABLE_REFLECTION_EMIT_SAVE */
+
+#ifndef DISABLE_REFLECTION_EMIT_SAVE
+
+static int
+calc_section_size (MonoDynamicImage *assembly)
+{
+ int nsections = 0;
+
+ /* alignment constraints */
+ mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
+ g_assert ((assembly->code.index % 4) == 0);
+ assembly->meta_size += 3;
+ assembly->meta_size &= ~3;
+ mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
+ g_assert ((assembly->resources.index % 4) == 0);
+
+ assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
+ assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
+ nsections++;
+
+ if (assembly->win32_res) {
+ guint32 res_size = (assembly->win32_res_size + 3) & ~3;
+
+ assembly->sections [MONO_SECTION_RSRC].size = res_size;
+ assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
+ nsections++;
+ }
+
+ assembly->sections [MONO_SECTION_RELOC].size = 12;
+ assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
+ nsections++;
+
+ return nsections;
+}
+
+typedef struct {
+ guint32 id;
+ guint32 offset;
+ GSList *children;
+ MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
+} ResTreeNode;
+
+static int
+resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
+{
+ ResTreeNode *t1 = (ResTreeNode*)a;
+ ResTreeNode *t2 = (ResTreeNode*)b;
+
+ return t1->id - t2->id;
+}
+
+/*
+ * resource_tree_create:
+ *
+ * Organize the resources into a resource tree.
+ */
+static ResTreeNode *
+resource_tree_create (MonoArray *win32_resources)
+{
+ ResTreeNode *tree, *res_node, *type_node, *lang_node;
+ GSList *l;
+ int i;
+
+ tree = g_new0 (ResTreeNode, 1);
+
+ for (i = 0; i < mono_array_length (win32_resources); ++i) {
+ MonoReflectionWin32Resource *win32_res =
+ (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
+
+ /* Create node */
+
+ /* FIXME: BUG: this stores managed references in unmanaged memory */
+ lang_node = g_new0 (ResTreeNode, 1);
+ lang_node->id = win32_res->lang_id;
+ lang_node->win32_res = win32_res;
+
+ /* Create type node if neccesary */
+ type_node = NULL;
+ for (l = tree->children; l; l = l->next)
+ if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
+ type_node = (ResTreeNode*)l->data;
+ break;
+ }
+
+ if (!type_node) {
+ type_node = g_new0 (ResTreeNode, 1);
+ type_node->id = win32_res->res_type;
+
+ /*
+ * The resource types have to be sorted otherwise
+ * Windows Explorer can't display the version information.
+ */
+ tree->children = g_slist_insert_sorted (tree->children,
+ type_node, resource_tree_compare_by_id);
+ }
+
+ /* Create res node if neccesary */
+ res_node = NULL;
+ for (l = type_node->children; l; l = l->next)
+ if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
+ res_node = (ResTreeNode*)l->data;
+ break;
+ }
+
+ if (!res_node) {
+ res_node = g_new0 (ResTreeNode, 1);
+ res_node->id = win32_res->res_id;
+ type_node->children = g_slist_append (type_node->children, res_node);
+ }
+
+ res_node->children = g_slist_append (res_node->children, lang_node);
+ }
+
+ return tree;
+}
+
+/*
+ * resource_tree_encode:
+ *
+ * Encode the resource tree into the format used in the PE file.
+ */
+static void
+resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
+{
+ char *entries;
+ MonoPEResourceDir dir;
+ MonoPEResourceDirEntry dir_entry;
+ MonoPEResourceDataEntry data_entry;
+ GSList *l;
+ guint32 res_id_entries;
+
+ /*
+ * For the format of the resource directory, see the article
+ * "An In-Depth Look into the Win32 Portable Executable File Format" by
+ * Matt Pietrek
+ */
+
+ memset (&dir, 0, sizeof (dir));
+ memset (&dir_entry, 0, sizeof (dir_entry));
+ memset (&data_entry, 0, sizeof (data_entry));
+
+ g_assert (sizeof (dir) == 16);
+ g_assert (sizeof (dir_entry) == 8);
+ g_assert (sizeof (data_entry) == 16);
+
+ node->offset = p - begin;
+
+ /* IMAGE_RESOURCE_DIRECTORY */
+ res_id_entries = g_slist_length (node->children);
+ dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
+
+ memcpy (p, &dir, sizeof (dir));
+ p += sizeof (dir);
+
+ /* Reserve space for entries */
+ entries = p;
+ p += sizeof (dir_entry) * res_id_entries;
+
+ /* Write children */
+ for (l = node->children; l; l = l->next) {
+ ResTreeNode *child = (ResTreeNode*)l->data;
+
+ if (child->win32_res) {
+ guint32 size;
+
+ child->offset = p - begin;
+
+ /* IMAGE_RESOURCE_DATA_ENTRY */
+ data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
+ size = mono_array_length (child->win32_res->res_data);
+ data_entry.rde_size = GUINT32_TO_LE (size);
+
+ memcpy (p, &data_entry, sizeof (data_entry));
+ p += sizeof (data_entry);
+
+ memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
+ p += size;
+ } else {
+ resource_tree_encode (child, begin, p, &p);
+ }
+ }
+
+ /* IMAGE_RESOURCE_ENTRY */
+ for (l = node->children; l; l = l->next) {
+ ResTreeNode *child = (ResTreeNode*)l->data;
+
+ MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
+ MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
+
+ memcpy (entries, &dir_entry, sizeof (dir_entry));
+ entries += sizeof (dir_entry);
+ }
+
+ *endbuf = p;
+}
+
+static void
+resource_tree_free (ResTreeNode * node)
+{
+ GSList * list;
+ for (list = node->children; list; list = list->next)
+ resource_tree_free ((ResTreeNode*)list->data);
+ g_slist_free(node->children);
+ g_free (node);
+}
+
+static void
+assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
+{
+ char *buf;
+ char *p;
+ guint32 size, i;
+ MonoReflectionWin32Resource *win32_res;
+ ResTreeNode *tree;
+
+ if (!assemblyb->win32_resources)
+ return;
+
+ /*
+ * Resources are stored in a three level tree inside the PE file.
+ * - level one contains a node for each type of resource
+ * - level two contains a node for each resource
+ * - level three contains a node for each instance of a resource for a
+ * specific language.
+ */
+
+ tree = resource_tree_create (assemblyb->win32_resources);
+
+ /* Estimate the size of the encoded tree */
+ size = 0;
+ for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
+ win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
+ size += mono_array_length (win32_res->res_data);
+ }
+ /* Directory structure */
+ size += mono_array_length (assemblyb->win32_resources) * 256;
+ p = buf = (char *)g_malloc (size);
+
+ resource_tree_encode (tree, p, p, &p);
+
+ g_assert (p - buf <= size);
+
+ assembly->win32_res = (char *)g_malloc (p - buf);
+ assembly->win32_res_size = p - buf;
+ memcpy (assembly->win32_res, buf, p - buf);
+
+ g_free (buf);
+ resource_tree_free (tree);
+}
+
+static void
+fixup_resource_directory (char *res_section, char *p, guint32 rva)
+{
+ MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
+ int i;
+
+ p += sizeof (MonoPEResourceDir);
+ for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
+ MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
+ char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
+ if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
+ fixup_resource_directory (res_section, child, rva);
+ } else {
+ MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
+ data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
+ }
+
+ p += sizeof (MonoPEResourceDirEntry);
+ }
+}
+
+static void
+checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
+{
+ guint32 dummy;
+ if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
+ g_error ("WriteFile returned %d\n", GetLastError ());
+}
+
+/*
+ * mono_image_create_pefile:
+ * @mb: a module builder object
+ *
+ * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
+ * assembly->pefile where it can be easily retrieved later in chunks.
+ */
+gboolean
+mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
+{
+ MonoMSDOSHeader *msdos;
+ MonoDotNetHeader *header;
+ MonoSectionTable *section;
+ MonoCLIHeader *cli_header;
+ guint32 size, image_size, virtual_base, text_offset;
+ guint32 header_start, section_start, file_offset, virtual_offset;
+ MonoDynamicImage *assembly;
+ MonoReflectionAssemblyBuilder *assemblyb;
+ MonoDynamicStream pefile_stream = {0};
+ MonoDynamicStream *pefile = &pefile_stream;
+ int i, nsections;
+ guint32 *rva, value;
+ guchar *p;
+ static const unsigned char msheader[] = {
+ 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+ 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ mono_error_init (error);
+
+ assemblyb = mb->assemblyb;
+
+ mono_reflection_dynimage_basic_init (assemblyb);
+ assembly = mb->dynamic_image;
+
+ assembly->pe_kind = assemblyb->pe_kind;
+ assembly->machine = assemblyb->machine;
+ ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
+ ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
+
+ if (!mono_image_build_metadata (mb, error))
+ return FALSE;
+
+
+ if (mb->is_main && assemblyb->resources) {
+ int len = mono_array_length (assemblyb->resources);
+ for (i = 0; i < len; ++i) {
+ if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
+ return FALSE;
+ }
+ }
+
+ if (mb->resources) {
+ int len = mono_array_length (mb->resources);
+ for (i = 0; i < len; ++i) {
+ if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
+ return FALSE;
+ }
+ }
+
+ if (!build_compressed_metadata (assembly, error))
+ return FALSE;
+
+ if (mb->is_main)
+ assembly_add_win32_resources (assembly, assemblyb);
+
+ nsections = calc_section_size (assembly);
+
+ /* The DOS header and stub */
+ g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
+ mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
+
+ /* the dotnet header */
+ header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
+
+ /* the section tables */
+ section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
+
+ file_offset = section_start + sizeof (MonoSectionTable) * nsections;
+ virtual_offset = VIRT_ALIGN;
+ image_size = 0;
+
+ for (i = 0; i < MONO_SECTION_MAX; ++i) {
+ if (!assembly->sections [i].size)
+ continue;
+ /* align offsets */
+ file_offset += FILE_ALIGN - 1;
+ file_offset &= ~(FILE_ALIGN - 1);
+ virtual_offset += VIRT_ALIGN - 1;
+ virtual_offset &= ~(VIRT_ALIGN - 1);
+
+ assembly->sections [i].offset = file_offset;
+ assembly->sections [i].rva = virtual_offset;
+
+ file_offset += assembly->sections [i].size;
+ virtual_offset += assembly->sections [i].size;
+ image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
+ }
+
+ file_offset += FILE_ALIGN - 1;
+ file_offset &= ~(FILE_ALIGN - 1);
+
+ image_size += section_start + sizeof (MonoSectionTable) * nsections;
+
+ /* back-patch info */
+ msdos = (MonoMSDOSHeader*)pefile->data;
+ msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
+
+ header = (MonoDotNetHeader*)(pefile->data + header_start);
+ header->pesig [0] = 'P';
+ header->pesig [1] = 'E';
+
+ header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
+ header->coff.coff_sections = GUINT16_FROM_LE (nsections);
+ header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
+ header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
+ if (assemblyb->pekind == 1) {
+ /* it's a dll */
+ header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
+ } else {
+ /* it's an exe */
+ header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
+ }
+
+ virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
+
+ header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
+ header->pe.pe_major = 6;
+ header->pe.pe_minor = 0;
+ size = assembly->sections [MONO_SECTION_TEXT].size;
+ size += FILE_ALIGN - 1;
+ size &= ~(FILE_ALIGN - 1);
+ header->pe.pe_code_size = GUINT32_FROM_LE(size);
+ size = assembly->sections [MONO_SECTION_RSRC].size;
+ size += FILE_ALIGN - 1;
+ size &= ~(FILE_ALIGN - 1);
+ header->pe.pe_data_size = GUINT32_FROM_LE(size);
+ g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
+ header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
+ header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
+ /* pe_rva_entry_point always at the beginning of the text section */
+ header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
+
+ header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
+ header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
+ header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
+ header->nt.pe_os_major = GUINT16_FROM_LE (4);
+ header->nt.pe_os_minor = GUINT16_FROM_LE (0);
+ header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
+ size = section_start;
+ size += FILE_ALIGN - 1;
+ size &= ~(FILE_ALIGN - 1);
+ header->nt.pe_header_size = GUINT32_FROM_LE (size);
+ size = image_size;
+ size += VIRT_ALIGN - 1;
+ size &= ~(VIRT_ALIGN - 1);
+ header->nt.pe_image_size = GUINT32_FROM_LE (size);
+
+ /*
+ // Translate the PEFileKind value to the value expected by the Windows loader
+ */
+ {
+ short kind;
+
+ /*
+ // PEFileKinds.Dll == 1
+ // PEFileKinds.ConsoleApplication == 2
+ // PEFileKinds.WindowApplication == 3
+ //
+ // need to get:
+ // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
+ // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
+ */
+ if (assemblyb->pekind == 3)
+ kind = 2;
+ else
+ kind = 3;
+
+ header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
+ }
+ header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
+ header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
+ header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
+ header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
+ header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
+ header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
+
+ /* fill data directory entries */
+
+ header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
+ header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
+
+ header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
+ header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
+
+ header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
+ header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
+ header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
+ header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
+ /* patch entrypoint name */
+ if (assemblyb->pekind == 1)
+ memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
+ else
+ memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
+ /* patch imported function RVA name */
+ rva = (guint32*)(assembly->code.data + assembly->iat_offset);
+ *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
+
+ /* the import table */
+ header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
+ header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
+ /* patch imported dll RVA name and other entries in the dir */
+ rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
+ *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
+ rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
+ *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
+ rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
+ *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
+
+ p = (guchar*)(assembly->code.data + assembly->ilt_offset);
+ value = (assembly->text_rva + assembly->imp_names_offset);
+ *p++ = (value) & 0xff;
+ *p++ = (value >> 8) & (0xff);
+ *p++ = (value >> 16) & (0xff);
+ *p++ = (value >> 24) & (0xff);
+
+ /* the CLI header info */
+ cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
+ cli_header->ch_size = GUINT32_FROM_LE (72);
+ cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
+ cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
+ cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
+ if (assemblyb->entry_point) {
+ guint32 table_idx = 0;
+ if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
+ MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
+ table_idx = methodb->table_idx;
+ } else {
+ table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
+ }
+ cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
+ } else {
+ cli_header->ch_entry_point = GUINT32_FROM_LE (0);
+ }
+ /* The embedded managed resources */
+ text_offset = assembly->text_rva + assembly->code.index;
+ cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
+ cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
+ text_offset += assembly->resources.index;
+ cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
+ cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
+ text_offset += assembly->meta_size;
+ if (assembly->strong_name_size) {
+ cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
+ cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
+ text_offset += assembly->strong_name_size;
+ }
+
+ /* write the section tables and section content */
+ section = (MonoSectionTable*)(pefile->data + section_start);
+ for (i = 0; i < MONO_SECTION_MAX; ++i) {
+ static const char section_names [][7] = {
+ ".text", ".rsrc", ".reloc"
+ };
+ if (!assembly->sections [i].size)
+ continue;
+ strcpy (section->st_name, section_names [i]);
+ /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
+ section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
+ section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
+ section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
+ section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
+ section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
+ section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
+ section ++;
+ }
+
+ checked_write_file (file, pefile->data, pefile->index);
+
+ mono_dynamic_stream_reset (pefile);
+
+ for (i = 0; i < MONO_SECTION_MAX; ++i) {
+ if (!assembly->sections [i].size)
+ continue;
+
+ if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ g_error ("SetFilePointer returned %d\n", GetLastError ());
+
+ switch (i) {
+ case MONO_SECTION_TEXT:
+ /* patch entry point */
+ p = (guchar*)(assembly->code.data + 2);
+ value = (virtual_base + assembly->text_rva + assembly->iat_offset);
+ *p++ = (value) & 0xff;
+ *p++ = (value >> 8) & 0xff;
+ *p++ = (value >> 16) & 0xff;
+ *p++ = (value >> 24) & 0xff;
+
+ checked_write_file (file, assembly->code.data, assembly->code.index);
+ checked_write_file (file, assembly->resources.data, assembly->resources.index);
+ checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
+ checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
+
+
+ g_free (assembly->image.raw_metadata);
+ break;
+ case MONO_SECTION_RELOC: {
+ struct {
+ guint32 page_rva;
+ guint32 block_size;
+ guint16 type_and_offset;
+ guint16 term;
+ } reloc;
+
+ g_assert (sizeof (reloc) == 12);
+
+ reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
+ reloc.block_size = GUINT32_FROM_LE (12);
+
+ /*
+ * the entrypoint is always at the start of the text section
+ * 3 is IMAGE_REL_BASED_HIGHLOW
+ * 2 is patch_size_rva - text_rva
+ */
+ reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
+ reloc.term = 0;
+
+ checked_write_file (file, &reloc, sizeof (reloc));
+
+ break;
+ }
+ case MONO_SECTION_RSRC:
+ if (assembly->win32_res) {
+
+ /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
+ fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
+ checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ /* check that the file is properly padded */
+ if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ g_error ("SetFilePointer returned %d\n", GetLastError ());
+ if (! SetEndOfFile (file))
+ g_error ("SetEndOfFile returned %d\n", GetLastError ());
+
+ mono_dynamic_stream_reset (&assembly->code);
+ mono_dynamic_stream_reset (&assembly->us);
+ mono_dynamic_stream_reset (&assembly->blob);
+ mono_dynamic_stream_reset (&assembly->guid);
+ mono_dynamic_stream_reset (&assembly->sheap);
+
+ g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
+ g_hash_table_destroy (assembly->blob_cache);
+ assembly->blob_cache = NULL;
+
+ return TRUE;
+}
+
+#else /* DISABLE_REFLECTION_EMIT_SAVE */
+
+gboolean
+mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
+{
+ g_assert_not_reached ();
+}
+
+#endif /* DISABLE_REFLECTION_EMIT_SAVE */
+
--- /dev/null
+/*
+ * sre.c: Routines for creating an image at runtime
+ * and related System.Reflection.Emit icalls
+ *
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+#include "mono/metadata/assembly.h"
+#include "mono/metadata/debug-helpers.h"
+#include "mono/metadata/dynamic-image-internals.h"
+#include "mono/metadata/dynamic-stream-internals.h"
+#include "mono/metadata/exception.h"
+#include "mono/metadata/gc-internals.h"
+#include "mono/metadata/mono-ptr-array.h"
+#include "mono/metadata/object-internals.h"
+#include "mono/metadata/profiler-private.h"
+#include "mono/metadata/reflection-internals.h"
+#include "mono/metadata/reflection-cache.h"
+#include "mono/metadata/sre-internals.h"
+#include "mono/metadata/custom-attrs-internals.h"
+#include "mono/metadata/security-manager.h"
+#include "mono/metadata/security-core-clr.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/tokentype.h"
+#include "mono/utils/checked-build.h"
+#include "mono/utils/mono-digest.h"
+
+void
+mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
+{
+ mono_gc_deregister_root ((char*) &entry->gparam);
+ g_free (entry);
+}
+
+
+
+static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
+
+#ifndef DISABLE_REFLECTION_EMIT
+static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
+static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
+static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
+static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
+static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
+static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
+static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
+
+static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+#endif
+
+static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
+static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
+static gboolean is_sre_array (MonoClass *klass);
+static gboolean is_sre_byref (MonoClass *klass);
+static gboolean is_sre_pointer (MonoClass *klass);
+static gboolean is_sre_type_builder (MonoClass *klass);
+static gboolean is_sre_method_builder (MonoClass *klass);
+static gboolean is_sre_field_builder (MonoClass *klass);
+static gboolean is_sr_mono_method (MonoClass *klass);
+static gboolean is_sr_mono_generic_method (MonoClass *klass);
+static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
+static gboolean is_sr_mono_field (MonoClass *klass);
+
+static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
+static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
+static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
+
+static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
+
+#define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
+
+static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
+
+void
+mono_reflection_emit_init (void)
+{
+ mono_dynamic_images_init ();
+}
+
+static char*
+type_get_fully_qualified_name (MonoType *type)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+}
+
+static char*
+type_get_qualified_name (MonoType *type, MonoAssembly *ass)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoClass *klass;
+ MonoAssembly *ta;
+
+ klass = mono_class_from_mono_type (type);
+ if (!klass)
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+ ta = klass->image->assembly;
+ if (assembly_is_dynamic (ta) || (ta == ass)) {
+ if (klass->generic_class || klass->generic_container)
+ /* For generic type definitions, we want T, while REFLECTION returns T<K> */
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
+ else
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+ }
+
+ return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+/**
+ * mp_g_alloc:
+ *
+ * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
+ * from the C heap.
+ */
+static gpointer
+image_g_malloc (MonoImage *image, guint size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (image)
+ return mono_image_alloc (image, size);
+ else
+ return g_malloc (size);
+}
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+/**
+ * image_g_alloc0:
+ *
+ * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
+ * from the C heap.
+ */
+gpointer
+mono_image_g_malloc0 (MonoImage *image, guint size)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (image)
+ return mono_image_alloc0 (image, size);
+ else
+ return g_malloc0 (size);
+}
+
+/**
+ * image_g_free:
+ * @image: a MonoImage
+ * @ptr: pointer
+ *
+ * If @image is NULL, free @ptr, otherwise do nothing.
+ */
+static void
+image_g_free (MonoImage *image, gpointer ptr)
+{
+ if (image == NULL)
+ g_free (ptr);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static char*
+image_strdup (MonoImage *image, const char *s)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ if (image)
+ return mono_image_strdup (image, s);
+ else
+ return g_strdup (s);
+}
+#endif
+
+#define image_g_new(image,struct_type, n_structs) \
+ ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+
+#define image_g_new0(image,struct_type, n_structs) \
+ ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+
+
+static void
+alloc_table (MonoDynamicTable *table, guint nrows)
+{
+ mono_dynimage_alloc_table (table, nrows);
+}
+
+static guint32
+string_heap_insert (MonoDynamicStream *sh, const char *str)
+{
+ return mono_dynstream_insert_string (sh, str);
+}
+
+static guint32
+string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
+{
+ return mono_dynstream_insert_mstring (sh, str, error);
+}
+
+static guint32
+mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+{
+ return mono_dynstream_add_data (stream, data, len);
+}
+
+static guint32
+mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
+{
+ return mono_dynstream_add_zero (stream, len);
+}
+
+static void
+stream_data_align (MonoDynamicStream *stream)
+{
+ mono_dynstream_data_align (stream);
+}
+
+/*
+ * Despite the name, we handle also TypeSpec (with the above helper).
+ */
+static guint32
+mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
+{
+ return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
+}
+
+/*
+ * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
+ * dest may be misaligned.
+ */
+static void
+swap_with_size (char *dest, const char* val, int len, int nelem) {
+ MONO_REQ_GC_NEUTRAL_MODE;
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ int elem;
+
+ for (elem = 0; elem < nelem; ++elem) {
+ switch (len) {
+ case 1:
+ *dest = *val;
+ break;
+ case 2:
+ dest [0] = val [1];
+ dest [1] = val [0];
+ break;
+ case 4:
+ dest [0] = val [3];
+ dest [1] = val [2];
+ dest [2] = val [1];
+ dest [3] = val [0];
+ break;
+ case 8:
+ dest [0] = val [7];
+ dest [1] = val [6];
+ dest [2] = val [5];
+ dest [3] = val [4];
+ dest [4] = val [3];
+ dest [5] = val [2];
+ dest [6] = val [1];
+ dest [7] = val [0];
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ dest += len;
+ val += len;
+ }
+#else
+ memcpy (dest, val, len * nelem);
+#endif
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static MonoClass *
+default_class_from_mono_type (MonoType *type)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ switch (type->type) {
+ case MONO_TYPE_OBJECT:
+ return mono_defaults.object_class;
+ case MONO_TYPE_VOID:
+ return mono_defaults.void_class;
+ case MONO_TYPE_BOOLEAN:
+ return mono_defaults.boolean_class;
+ case MONO_TYPE_CHAR:
+ return mono_defaults.char_class;
+ case MONO_TYPE_I1:
+ return mono_defaults.sbyte_class;
+ case MONO_TYPE_U1:
+ return mono_defaults.byte_class;
+ case MONO_TYPE_I2:
+ return mono_defaults.int16_class;
+ case MONO_TYPE_U2:
+ return mono_defaults.uint16_class;
+ case MONO_TYPE_I4:
+ return mono_defaults.int32_class;
+ case MONO_TYPE_U4:
+ return mono_defaults.uint32_class;
+ case MONO_TYPE_I:
+ return mono_defaults.int_class;
+ case MONO_TYPE_U:
+ return mono_defaults.uint_class;
+ case MONO_TYPE_I8:
+ return mono_defaults.int64_class;
+ case MONO_TYPE_U8:
+ return mono_defaults.uint64_class;
+ case MONO_TYPE_R4:
+ return mono_defaults.single_class;
+ case MONO_TYPE_R8:
+ return mono_defaults.double_class;
+ case MONO_TYPE_STRING:
+ return mono_defaults.string_class;
+ default:
+ g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
+ g_assert_not_reached ();
+ }
+
+ return NULL;
+}
+#endif
+
+guint32
+mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ guint32 num_clauses = 0;
+ int i;
+
+ MonoILExceptionInfo *ex_info;
+ for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
+ ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
+ if (ex_info->handlers)
+ num_clauses += mono_array_length (ex_info->handlers);
+ else
+ num_clauses++;
+ }
+
+ return num_clauses;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static MonoExceptionClause*
+method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+
+ MonoExceptionClause *clauses;
+ MonoExceptionClause *clause;
+ MonoILExceptionInfo *ex_info;
+ MonoILExceptionBlock *ex_block;
+ guint32 finally_start;
+ int i, j, clause_index;;
+
+ clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
+
+ clause_index = 0;
+ for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
+ ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
+ finally_start = ex_info->start + ex_info->len;
+ if (!ex_info->handlers)
+ continue;
+ for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
+ ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
+ clause = &(clauses [clause_index]);
+
+ clause->flags = ex_block->type;
+ clause->try_offset = ex_info->start;
+
+ if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
+ clause->try_len = finally_start - ex_info->start;
+ else
+ clause->try_len = ex_info->len;
+ clause->handler_offset = ex_block->start;
+ clause->handler_len = ex_block->len;
+ if (ex_block->extype) {
+ MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
+
+ if (!is_ok (error)) {
+ image_g_free (image, clauses);
+ return NULL;
+ }
+ clause->data.catch_class = mono_class_from_mono_type (extype);
+ } else {
+ if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
+ clause->data.filter_offset = ex_block->filter_offset;
+ else
+ clause->data.filter_offset = 0;
+ }
+ finally_start = ex_block->start + ex_block->len;
+
+ clause_index ++;
+ }
+ }
+
+ return clauses;
+}
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+/*
+ * LOCKING: Acquires the loader lock.
+ */
+static void
+mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoCustomAttrInfo *ainfo, *tmp;
+
+ if (!cattrs || !mono_array_length (cattrs))
+ return;
+
+ ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
+
+ mono_loader_lock ();
+ tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
+ if (tmp)
+ mono_custom_attrs_free (tmp);
+ mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
+ mono_loader_unlock ();
+
+}
+#endif
+
+
+guint32
+mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoDynamicTable *table;
+ guint32 token;
+ guint32 *values;
+ guint32 cols [MONO_ASSEMBLY_SIZE];
+ const char *pubkey;
+ guint32 publen;
+
+ if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
+ return token;
+
+ if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
+ table = &assembly->tables [MONO_TABLE_MODULEREF];
+ token = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + token * MONO_MODULEREF_SIZE;
+ values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
+
+ token <<= MONO_RESOLUTION_SCOPE_BITS;
+ token |= MONO_RESOLUTION_SCOPE_MODULEREF;
+ g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
+
+ return token;
+ }
+
+ if (assembly_is_dynamic (image->assembly))
+ /* FIXME: */
+ memset (cols, 0, sizeof (cols));
+ else {
+ /* image->assembly->image is the manifest module */
+ image = image->assembly->image;
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
+ }
+
+ table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
+ token = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + token * MONO_ASSEMBLYREF_SIZE;
+ values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
+ values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
+ values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
+ values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
+ values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
+ values [MONO_ASSEMBLYREF_FLAGS] = 0;
+ values [MONO_ASSEMBLYREF_CULTURE] = 0;
+ values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
+
+ if (strcmp ("", image->assembly->aname.culture)) {
+ values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
+ image->assembly->aname.culture);
+ }
+
+ if ((pubkey = mono_image_get_public_key (image, &publen))) {
+ guchar pubtoken [9];
+ pubtoken [0] = 8;
+ mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
+ } else {
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
+ }
+ token <<= MONO_RESOLUTION_SCOPE_BITS;
+ token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
+ g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
+ return token;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+gboolean
+mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ mono_error_init (error);
+ memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
+ rmb->ilgen = mb->ilgen;
+ rmb->rtype = (MonoReflectionType*)mb->rtype;
+ return_val_if_nok (error, FALSE);
+ rmb->parameters = mb->parameters;
+ rmb->generic_params = mb->generic_params;
+ rmb->generic_container = mb->generic_container;
+ rmb->opt_types = NULL;
+ rmb->pinfo = mb->pinfo;
+ rmb->attrs = mb->attrs;
+ rmb->iattrs = mb->iattrs;
+ rmb->call_conv = mb->call_conv;
+ rmb->code = mb->code;
+ rmb->type = mb->type;
+ rmb->name = mb->name;
+ rmb->table_idx = &mb->table_idx;
+ rmb->init_locals = mb->init_locals;
+ rmb->skip_visibility = FALSE;
+ rmb->return_modreq = mb->return_modreq;
+ rmb->return_modopt = mb->return_modopt;
+ rmb->param_modreq = mb->param_modreq;
+ rmb->param_modopt = mb->param_modopt;
+ rmb->permissions = mb->permissions;
+ rmb->mhandle = mb->mhandle;
+ rmb->nrefs = 0;
+ rmb->refs = NULL;
+
+ if (mb->dll) {
+ rmb->charset = mb->charset;
+ rmb->extra_flags = mb->extra_flags;
+ rmb->native_cc = mb->native_cc;
+ rmb->dllentry = mb->dllentry;
+ rmb->dll = mb->dll;
+ }
+
+ return TRUE;
+}
+
+gboolean
+mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+
+ mono_error_init (error);
+
+ memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
+ rmb->ilgen = mb->ilgen;
+ rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
+ return_val_if_nok (error, FALSE);
+ rmb->parameters = mb->parameters;
+ rmb->generic_params = NULL;
+ rmb->generic_container = NULL;
+ rmb->opt_types = NULL;
+ rmb->pinfo = mb->pinfo;
+ rmb->attrs = mb->attrs;
+ rmb->iattrs = mb->iattrs;
+ rmb->call_conv = mb->call_conv;
+ rmb->code = NULL;
+ rmb->type = mb->type;
+ rmb->name = mono_string_new (mono_domain_get (), name);
+ rmb->table_idx = &mb->table_idx;
+ rmb->init_locals = mb->init_locals;
+ rmb->skip_visibility = FALSE;
+ rmb->return_modreq = NULL;
+ rmb->return_modopt = NULL;
+ rmb->param_modreq = mb->param_modreq;
+ rmb->param_modopt = mb->param_modopt;
+ rmb->permissions = mb->permissions;
+ rmb->mhandle = mb->mhandle;
+ rmb->nrefs = 0;
+ rmb->refs = NULL;
+
+ return TRUE;
+}
+
+static void
+reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
+ rmb->ilgen = mb->ilgen;
+ rmb->rtype = mb->rtype;
+ rmb->parameters = mb->parameters;
+ rmb->generic_params = NULL;
+ rmb->generic_container = NULL;
+ rmb->opt_types = NULL;
+ rmb->pinfo = NULL;
+ rmb->attrs = mb->attrs;
+ rmb->iattrs = 0;
+ rmb->call_conv = mb->call_conv;
+ rmb->code = NULL;
+ rmb->type = (MonoObject *) mb->owner;
+ rmb->name = mb->name;
+ rmb->table_idx = NULL;
+ rmb->init_locals = mb->init_locals;
+ rmb->skip_visibility = mb->skip_visibility;
+ rmb->return_modreq = NULL;
+ rmb->return_modopt = NULL;
+ rmb->param_modreq = NULL;
+ rmb->param_modopt = NULL;
+ rmb->permissions = NULL;
+ rmb->mhandle = mb->mhandle;
+ rmb->nrefs = 0;
+ rmb->refs = NULL;
+}
+#else /* DISABLE_REFLECTION_EMIT */
+gboolean
+mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
+ g_assert_not_reached ();
+ return FALSE;
+}
+gboolean
+mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
+{
+ g_assert_not_reached ();
+ return FALSE;
+}
+#endif /* DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+static guint32
+mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token, pclass;
+
+ switch (parent & MONO_TYPEDEFORREF_MASK) {
+ case MONO_TYPEDEFORREF_TYPEREF:
+ pclass = MONO_MEMBERREF_PARENT_TYPEREF;
+ break;
+ case MONO_TYPEDEFORREF_TYPESPEC:
+ pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
+ break;
+ case MONO_TYPEDEFORREF_TYPEDEF:
+ pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
+ break;
+ default:
+ g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
+ return 0;
+ }
+ /* extract the index */
+ parent >>= MONO_TYPEDEFORREF_BITS;
+
+ table = &assembly->tables [MONO_TABLE_MEMBERREF];
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_MEMBER_REF | table->next_idx;
+ table->next_idx ++;
+
+ return token;
+}
+
+/*
+ * Insert a memberef row into the metadata: the token that point to the memberref
+ * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
+ * mono_image_get_fieldref_token()).
+ * The sig param is an index to an already built signature.
+ */
+static guint32
+mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 parent = mono_image_typedef_or_ref (assembly, type);
+ return mono_image_add_memberef_row (assembly, parent, name, sig);
+}
+
+
+static guint32
+mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
+{
+ MONO_REQ_GC_NEUTRAL_MODE;
+
+ guint32 token;
+ MonoMethodSignature *sig;
+
+ create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
+
+ if (create_typespec) {
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
+ if (token)
+ return token;
+ }
+
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
+ if (token && !create_typespec)
+ return token;
+
+ g_assert (!method->is_inflated);
+ if (!token) {
+ /*
+ * A methodref signature can't contain an unmanaged calling convention.
+ */
+ sig = mono_metadata_signature_dup (mono_method_signature (method));
+ if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
+ sig->call_convention = MONO_CALL_DEFAULT;
+ token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
+ method->name, mono_dynimage_encode_method_signature (assembly, sig));
+ g_free (sig);
+ g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
+ }
+
+ if (create_typespec) {
+ MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
+ g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
+ token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
+
+ if (assembly->save) {
+ guint32 *values;
+
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
+ values [MONO_METHODSPEC_METHOD] = token;
+ values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
+ }
+
+ token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
+ table->next_idx ++;
+ /*methodspec and memberef tokens are diferent, */
+ g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
+ return token;
+ }
+ return token;
+}
+
+static guint32
+mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
+{
+ guint32 token, parent, sig;
+ ReflectionMethodBuilder rmb;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
+
+ mono_error_init (error);
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
+ if (token)
+ return token;
+
+ if (!mono_reflection_methodbuilder_from_method_builder (&rmb, method, error))
+ return 0;
+
+ /*
+ * A methodref signature can't contain an unmanaged calling convention.
+ * Since some flags are encoded as part of call_conv, we need to check against it.
+ */
+ if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
+ rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
+
+ sig = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
+ return_val_if_nok (error, 0);
+
+ if (tb->generic_params) {
+ parent = mono_dynimage_encode_generic_typespec (assembly, tb, error);
+ return_val_if_nok (error, 0);
+ } else {
+ MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
+ return_val_if_nok (error, 0);
+
+ parent = mono_image_typedef_or_ref (assembly, t);
+ }
+
+ char *name = mono_string_to_utf8_checked (method->name, error);
+ return_val_if_nok (error, 0);
+
+ token = mono_image_add_memberef_row (assembly, parent, name, sig);
+ g_free (name);
+
+ g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
+
+ return token;
+}
+
+static guint32
+mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
+ const gchar *name, guint32 sig)
+{
+ MonoDynamicTable *table;
+ guint32 token;
+ guint32 *values;
+
+ table = &assembly->tables [MONO_TABLE_MEMBERREF];
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = original;
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_MEMBER_REF | table->next_idx;
+ table->next_idx ++;
+
+ return token;
+}
+
+static guint32
+mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token, mtoken = 0;
+
+ mono_error_init (error);
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
+ if (token)
+ return token;
+
+ table = &assembly->tables [MONO_TABLE_METHODSPEC];
+
+ mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
+ if (!mono_error_ok (error))
+ return 0;
+
+ switch (mono_metadata_token_table (mtoken)) {
+ case MONO_TABLE_MEMBERREF:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
+ break;
+ case MONO_TABLE_METHOD:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
+ values [MONO_METHODSPEC_METHOD] = mtoken;
+ values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_definition_sig (assembly, mb);
+ }
+
+ token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
+ table->next_idx ++;
+
+ mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
+{
+ guint32 token;
+
+ mono_error_init (error);
+
+ if (mb->generic_params && create_methodspec)
+ return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
+ if (token)
+ return token;
+
+ token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
+ if (!mono_error_ok (error))
+ return 0;
+ mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
+{
+ guint32 token, parent, sig;
+ ReflectionMethodBuilder rmb;
+ char *name;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
+
+ mono_error_init (error);
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
+ if (token)
+ return token;
+
+ if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
+ return 0;
+
+ if (tb->generic_params) {
+ parent = mono_dynimage_encode_generic_typespec (assembly, tb, error);
+ return_val_if_nok (error, 0);
+ } else {
+ MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+ return_val_if_nok (error, 0);
+ parent = mono_image_typedef_or_ref (assembly, type);
+ }
+
+ name = mono_string_to_utf8_checked (rmb.name, error);
+ return_val_if_nok (error, 0);
+ sig = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
+ return_val_if_nok (error, 0);
+
+ token = mono_image_add_memberef_row (assembly, parent, name, sig);
+
+ g_free (name);
+ mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
+ return token;
+}
+#endif
+
+static gboolean
+is_field_on_inst (MonoClassField *field)
+{
+ return field->parent->generic_class && field->parent->generic_class->is_dynamic;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static guint32
+mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
+{
+ MonoType *type;
+ guint32 token;
+
+ g_assert (field);
+ g_assert (field->parent);
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
+ if (token)
+ return token;
+
+ if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
+ int index = field - field->parent->fields;
+ type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
+ } else {
+ type = mono_field_get_type (field);
+ }
+ token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
+ mono_field_get_name (field),
+ mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
+ mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
+{
+ guint32 token;
+ MonoClass *klass;
+ MonoGenericClass *gclass;
+ MonoType *type;
+ char *name;
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
+ if (token)
+ return token;
+ if (is_sre_field_builder (mono_object_class (f->fb))) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+ gclass = type->data.generic_class;
+ g_assert (gclass->is_dynamic);
+
+ guint32 sig_token = mono_dynimage_encode_field_signature (assembly, fb, error);
+ return_val_if_nok (error, 0);
+ name = mono_string_to_utf8_checked (fb->name, error);
+ return_val_if_nok (error, 0);
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
+ g_free (name);
+ } else if (is_sr_mono_field (mono_object_class (f->fb))) {
+ guint32 sig;
+ MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+
+ sig = mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, field->type);
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
+ } else {
+ char *name = mono_type_get_full_name (mono_object_class (f->fb));
+ g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
+ }
+
+ mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
+ return token;
+}
+
+static guint32
+mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
+{
+ guint32 sig, token;
+ MonoClass *klass;
+ MonoGenericClass *gclass;
+ MonoType *type;
+
+ mono_error_init (error);
+
+ /* A ctor cannot be a generic method, so we can ignore create_methodspec */
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
+ if (token)
+ return token;
+
+ if (mono_is_sre_ctor_builder (mono_object_class (c->cb))) {
+ MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
+ ReflectionMethodBuilder rmb;
+ char *name;
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+
+ gclass = type->data.generic_class;
+ g_assert (gclass->is_dynamic);
+
+ if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
+ return 0;
+
+ sig = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
+ return_val_if_nok (error, 0);
+
+ name = mono_string_to_utf8_checked (rmb.name, error);
+ return_val_if_nok (error, 0);
+
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
+ g_free (name);
+ } else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb))) {
+ MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+
+ sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (mm));
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
+ } else {
+ char *name = mono_type_get_full_name (mono_object_class (c->cb));
+ g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
+ }
+
+
+ mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
+ return token;
+}
+
+MonoMethod*
+mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
+{
+ MonoClass *klass;
+ MonoGenericContext tmp_context;
+ MonoType **type_argv;
+ MonoGenericInst *ginst;
+ MonoMethod *method, *inflated;
+ int count, i;
+
+ mono_error_init (error);
+
+ mono_reflection_init_type_builder_generics ((MonoObject*)m->inst, error);
+ return_val_if_nok (error, NULL);
+
+ method = inflate_method (m->inst, (MonoObject*)m->mb, error);
+ return_val_if_nok (error, NULL);
+
+ klass = method->klass;
+
+ if (m->method_args == NULL)
+ return method;
+
+ if (method->is_inflated)
+ method = ((MonoMethodInflated *) method)->declaring;
+
+ count = mono_array_length (m->method_args);
+
+ type_argv = g_new0 (MonoType *, count);
+ for (i = 0; i < count; i++) {
+ MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
+ type_argv [i] = mono_reflection_type_get_handle (garg, error);
+ return_val_if_nok (error, NULL);
+ }
+ ginst = mono_metadata_get_generic_inst (count, type_argv);
+ g_free (type_argv);
+
+ tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ tmp_context.method_inst = ginst;
+
+ inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
+ mono_error_assert_ok (error);
+ return inflated;
+}
+
+static guint32
+mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
+{
+ guint32 sig, token = 0;
+ MonoType *type;
+ MonoClass *klass;
+
+ mono_error_init (error);
+
+ if (m->method_args) {
+ MonoMethod *inflated;
+
+ inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
+ return_val_if_nok (error, 0);
+
+ if (create_methodspec)
+ token = mono_image_get_methodspec_token (assembly, inflated);
+ else
+ token = mono_image_get_inflated_method_token (assembly, inflated);
+ return token;
+ }
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
+ if (token)
+ return token;
+
+ if (is_sre_method_builder (mono_object_class (m->mb))) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
+ MonoGenericClass *gclass;
+ ReflectionMethodBuilder rmb;
+ char *name;
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+ gclass = type->data.generic_class;
+ g_assert (gclass->is_dynamic);
+
+ if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
+ return 0;
+
+ sig = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
+ return_val_if_nok (error, 0);
+
+ name = mono_string_to_utf8_checked (rmb.name, error);
+ return_val_if_nok (error, 0);
+
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
+ g_free (name);
+ } else if (is_sr_mono_method (mono_object_class (m->mb))) {
+ MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
+
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+ return_val_if_nok (error, 0);
+ klass = mono_class_from_mono_type (type);
+
+ sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (mm));
+ token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
+ } else {
+ char *name = mono_type_get_full_name (mono_object_class (m->mb));
+ g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
+ }
+
+ mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
+ return token;
+}
+
+static guint32
+method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token, mtoken = 0, sig;
+ MonoMethodInflated *imethod;
+ MonoMethod *declaring;
+
+ table = &assembly->tables [MONO_TABLE_METHODSPEC];
+
+ g_assert (method->is_inflated);
+ imethod = (MonoMethodInflated *) method;
+ declaring = imethod->declaring;
+
+ sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (declaring));
+ mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
+
+ if (!mono_method_signature (declaring)->generic_param_count)
+ return mtoken;
+
+ switch (mono_metadata_token_table (mtoken)) {
+ case MONO_TABLE_MEMBERREF:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
+ break;
+ case MONO_TABLE_METHOD:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
+ values [MONO_METHODSPEC_METHOD] = mtoken;
+ values [MONO_METHODSPEC_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
+ table->next_idx ++;
+
+ return token;
+}
+
+static guint32
+mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
+{
+ MonoMethodInflated *imethod;
+ guint32 token;
+
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
+ if (token)
+ return token;
+
+ g_assert (method->is_inflated);
+ imethod = (MonoMethodInflated *) method;
+
+ if (mono_method_signature (imethod->declaring)->generic_param_count) {
+ token = method_encode_methodspec (assembly, method);
+ } else {
+ guint32 sig = mono_dynimage_encode_method_signature (
+ assembly, mono_method_signature (imethod->declaring));
+ token = mono_image_get_memberref_token (
+ assembly, &method->klass->byval_arg, method->name, sig);
+ }
+
+ g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
+{
+ MonoMethodInflated *imethod = (MonoMethodInflated *) m;
+ guint32 sig, token;
+
+ sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (imethod->declaring));
+ token = mono_image_get_memberref_token (
+ assembly, &m->klass->byval_arg, m->name, sig);
+
+ return token;
+}
+
+/*
+ * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
+ */
+static MonoType*
+add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
+{
+ int i, count, len, pos;
+ MonoType *t;
+
+ mono_error_init (error);
+
+ count = 0;
+ if (modreq)
+ count += mono_array_length (modreq);
+ if (modopt)
+ count += mono_array_length (modopt);
+
+ if (count == 0)
+ return mono_metadata_type_dup (NULL, type);
+
+ len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
+ t = (MonoType *)g_malloc (len);
+ memcpy (t, type, MONO_SIZEOF_TYPE);
+
+ t->num_mods = count;
+ pos = 0;
+ if (modreq) {
+ for (i = 0; i < mono_array_length (modreq); ++i) {
+ MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
+ if (!is_ok (error))
+ goto fail;
+ t->modifiers [pos].required = 1;
+ t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
+ pos ++;
+ }
+ }
+ if (modopt) {
+ for (i = 0; i < mono_array_length (modopt); ++i) {
+ MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
+ if (!is_ok (error))
+ goto fail;
+ t->modifiers [pos].required = 0;
+ t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
+ pos ++;
+ }
+ }
+
+ return t;
+fail:
+ g_free (t);
+ return NULL;
+}
+
+void
+mono_reflection_init_type_builder_generics (MonoObject *type, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb;
+
+ mono_error_init (error);
+
+ if (!is_sre_type_builder(mono_object_class (type)))
+ return;
+ tb = (MonoReflectionTypeBuilder *)type;
+
+ if (tb && tb->generic_container)
+ mono_reflection_create_generic_class (tb, error);
+}
+
+static guint32
+mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
+{
+ MonoDynamicTable *table;
+ MonoType *custom = NULL, *type;
+ guint32 *values;
+ guint32 token, pclass, parent, sig;
+ gchar *name;
+
+ mono_error_init (error);
+
+ token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
+ if (token)
+ return token;
+
+ MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
+ return_val_if_nok (error, 0);
+ /* FIXME: is this call necessary? */
+ mono_class_from_mono_type (typeb);
+
+ /*FIXME this is one more layer of ugliness due how types are created.*/
+ mono_reflection_init_type_builder_generics (fb->type, error);
+ return_val_if_nok (error, 0);
+
+ /* fb->type does not include the custom modifiers */
+ /* FIXME: We should do this in one place when a fieldbuilder is created */
+ type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ return_val_if_nok (error, 0);
+
+ if (fb->modreq || fb->modopt) {
+ type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
+ return_val_if_nok (error, 0);
+ }
+
+ sig = mono_dynimage_encode_fieldref_signature (assembly, NULL, type);
+ g_free (custom);
+
+ parent = mono_dynimage_encode_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
+ return_val_if_nok (error, 0);
+ g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
+
+ pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
+ parent >>= MONO_TYPEDEFORREF_BITS;
+
+ table = &assembly->tables [MONO_TABLE_MEMBERREF];
+
+ name = mono_string_to_utf8_checked (fb->name, error);
+ return_val_if_nok (error, 0);
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_MEMBER_REF | table->next_idx;
+ table->next_idx ++;
+ mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
+ g_free (name);
+ return token;
+}
+
+static guint32
+mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
+{
+ guint32 idx;
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ mono_error_init (error);
+
+ table = &assembly->tables [MONO_TABLE_STANDALONESIG];
+ idx = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
+
+ values [MONO_STAND_ALONE_SIGNATURE] =
+ mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
+ return_val_if_nok (error, 0);
+
+ return idx;
+}
+
+static int
+reflection_cc_to_file (int call_conv) {
+ switch (call_conv & 0x3) {
+ case 0:
+ case 1: return MONO_CALL_DEFAULT;
+ case 2: return MONO_CALL_VARARG;
+ default:
+ g_assert_not_reached ();
+ }
+ return 0;
+}
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+struct _ArrayMethod {
+ MonoType *parent;
+ MonoMethodSignature *sig;
+ char *name;
+ guint32 token;
+};
+
+void
+mono_sre_array_method_free (ArrayMethod *am)
+{
+ g_free (am->sig);
+ g_free (am->name);
+ g_free (am);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static guint32
+mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
+{
+ guint32 nparams, i;
+ GList *tmp;
+ char *name = NULL;
+ MonoMethodSignature *sig;
+ ArrayMethod *am = NULL;
+ MonoType *mtype;
+
+ mono_error_init (error);
+
+ nparams = mono_array_length (m->parameters);
+ sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
+ sig->hasthis = 1;
+ sig->sentinelpos = -1;
+ sig->call_convention = reflection_cc_to_file (m->call_conv);
+ sig->param_count = nparams;
+ if (m->ret) {
+ sig->ret = mono_reflection_type_get_handle (m->ret, error);
+ if (!is_ok (error))
+ goto fail;
+ } else
+ sig->ret = &mono_defaults.void_class->byval_arg;
+
+ mtype = mono_reflection_type_get_handle (m->parent, error);
+ if (!is_ok (error))
+ goto fail;
+
+ for (i = 0; i < nparams; ++i) {
+ sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
+ if (!is_ok (error))
+ goto fail;
+ }
+
+ name = mono_string_to_utf8_checked (m->name, error);
+ if (!is_ok (error))
+ goto fail;
+ for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
+ am = (ArrayMethod *)tmp->data;
+ if (strcmp (name, am->name) == 0 &&
+ mono_metadata_type_equal (am->parent, mtype) &&
+ mono_metadata_signature_equal (am->sig, sig)) {
+ g_free (name);
+ g_free (sig);
+ m->table_idx = am->token & 0xffffff;
+ return am->token;
+ }
+ }
+ am = g_new0 (ArrayMethod, 1);
+ am->name = name;
+ am->sig = sig;
+ am->parent = mtype;
+ am->token = mono_image_get_memberref_token (assembly, am->parent, name,
+ mono_dynimage_encode_method_signature (assembly, sig));
+ assembly->array_methods = g_list_prepend (assembly->array_methods, am);
+ m->table_idx = am->token & 0xffffff;
+ return am->token;
+fail:
+ g_free (am);
+ g_free (name);
+ g_free (sig);
+ return 0;
+
+}
+#endif
+
+#ifndef DISABLE_REFLECTION_EMIT
+
+/*
+ * mono_image_insert_string:
+ * @module: module builder object
+ * @str: a string
+ *
+ * Insert @str into the user string stream of @module.
+ */
+guint32
+mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
+{
+ MonoDynamicImage *assembly;
+ guint32 idx;
+ char buf [16];
+ char *b = buf;
+
+ if (!module->dynamic_image)
+ mono_image_module_basic_init (module);
+
+ assembly = module->dynamic_image;
+
+ if (assembly->save) {
+ mono_metadata_encode_value (1 | (str->length * 2), b, &b);
+ idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ {
+ char *swapped = g_malloc (2 * mono_string_length (str));
+ const char *p = (const char*)mono_string_chars (str);
+
+ swap_with_size (swapped, p, 2, mono_string_length (str));
+ mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
+ g_free (swapped);
+ }
+#else
+ mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
+#endif
+ mono_image_add_stream_data (&assembly->us, "", 1);
+ } else {
+ idx = assembly->us.index ++;
+ }
+
+ mono_dynamic_image_register_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
+
+ return MONO_TOKEN_STRING | idx;
+}
+
+guint32
+mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
+{
+ MonoClass *klass;
+ guint32 token = 0;
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ klass = obj->vtable->klass;
+ if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
+ MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
+ MonoMethodSignature *old;
+ guint32 sig_token, parent;
+ int nargs, i;
+
+ g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
+
+ nargs = mono_array_length (opt_param_types);
+ old = mono_method_signature (method);
+ sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
+
+ sig->hasthis = old->hasthis;
+ sig->explicit_this = old->explicit_this;
+ sig->call_convention = old->call_convention;
+ sig->generic_param_count = old->generic_param_count;
+ sig->param_count = old->param_count + nargs;
+ sig->sentinelpos = old->param_count;
+ sig->ret = old->ret;
+
+ for (i = 0; i < old->param_count; i++)
+ sig->params [i] = old->params [i];
+
+ for (i = 0; i < nargs; i++) {
+ MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
+ sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
+ if (!is_ok (error)) goto fail;
+ }
+
+ parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
+ g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
+ parent >>= MONO_TYPEDEFORREF_BITS;
+
+ parent <<= MONO_MEMBERREF_PARENT_BITS;
+ parent |= MONO_MEMBERREF_PARENT_TYPEREF;
+
+ sig_token = mono_dynimage_encode_method_signature (assembly, sig);
+ token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
+ } else if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
+ ReflectionMethodBuilder rmb;
+ guint32 parent, sig_token;
+ int nopt_args, nparams, ngparams, i;
+
+ if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
+ goto fail;
+
+ rmb.opt_types = opt_param_types;
+ nopt_args = mono_array_length (opt_param_types);
+
+ nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
+ ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
+ sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
+
+ sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
+ sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
+ sig->call_convention = rmb.call_conv;
+ sig->generic_param_count = ngparams;
+ sig->param_count = nparams + nopt_args;
+ sig->sentinelpos = nparams;
+ sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
+ if (!is_ok (error)) goto fail;
+
+ for (i = 0; i < nparams; i++) {
+ MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
+ sig->params [i] = mono_reflection_type_get_handle (rt, error);
+ if (!is_ok (error)) goto fail;
+ }
+
+ for (i = 0; i < nopt_args; i++) {
+ MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
+ sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
+ if (!is_ok (error)) goto fail;
+ }
+
+ sig_token = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
+ if (!is_ok (error))
+ goto fail;
+
+ parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
+ if (!mono_error_ok (error))
+ goto fail;
+ g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
+
+ parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
+ parent |= MONO_MEMBERREF_PARENT_METHODDEF;
+
+ char *name = mono_string_to_utf8_checked (rmb.name, error);
+ if (!is_ok (error)) goto fail;
+ token = mono_image_get_varargs_method_token (
+ assembly, parent, name, sig_token);
+ g_free (name);
+ } else {
+ g_error ("requested method token for %s\n", klass->name);
+ }
+
+ g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
+ mono_dynamic_image_register_token (assembly, token, obj);
+ return token;
+fail:
+ g_assert (!mono_error_ok (error));
+ return 0;
+}
+
+/*
+ * mono_image_create_token:
+ * @assembly: a dynamic assembly
+ * @obj:
+ * @register_token: Whenever to register the token in the assembly->tokens hash.
+ *
+ * Get a token to insert in the IL code stream for the given MemberInfo.
+ * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
+ * the table_idx-es were recomputed, so registering the token would overwrite an existing
+ * entry.
+ */
+guint32
+mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
+ gboolean create_open_instance, gboolean register_token,
+ MonoError *error)
+{
+ MonoClass *klass;
+ guint32 token = 0;
+
+ mono_error_init (error);
+
+ klass = obj->vtable->klass;
+
+ /* Check for user defined reflection objects */
+ /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
+ if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
+ mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
+ return 0;
+ }
+
+ if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
+
+ if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ else {
+ token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
+ if (!mono_error_ok (error))
+ return 0;
+ }
+ /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
+ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
+
+ if (tb->module->dynamic_image == assembly && !tb->generic_params)
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ else {
+ token = mono_image_get_ctorbuilder_token (assembly, mb, error);
+ if (!mono_error_ok (error))
+ return 0;
+ }
+ /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
+ } else if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
+ if (tb->generic_params) {
+ token = mono_image_get_generic_field_token (assembly, fb, error);
+ return_val_if_nok (error, 0);
+ } else {
+ if (tb->module->dynamic_image == assembly) {
+ token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+ } else {
+ token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
+ }
+ }
+ } else if (strcmp (klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
+ if (create_open_instance && tb->generic_params) {
+ MonoType *type;
+ mono_reflection_init_type_builder_generics (obj, error);
+ return_val_if_nok (error, 0);
+ type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
+ token = mono_metadata_token_from_dor (token);
+ } else if (tb->module->dynamic_image == assembly) {
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ } else {
+ MonoType *type;
+ type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
+ }
+ } else if (strcmp (klass->name, "RuntimeType") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ MonoClass *mc = mono_class_from_mono_type (type);
+ token = mono_metadata_token_from_dor (
+ mono_dynimage_encode_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
+ } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_metadata_token_from_dor (
+ mono_image_typedef_or_ref (assembly, type));
+ } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_metadata_token_from_dor (
+ mono_image_typedef_or_ref (assembly, type));
+ } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ strcmp (klass->name, "MonoMethod") == 0 ||
+ strcmp (klass->name, "MonoGenericMethod") == 0 ||
+ strcmp (klass->name, "MonoGenericCMethod") == 0) {
+ MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
+ if (m->method->is_inflated) {
+ if (create_open_instance)
+ token = mono_image_get_methodspec_token (assembly, m->method);
+ else
+ token = mono_image_get_inflated_method_token (assembly, m->method);
+ } else if ((m->method->klass->image == &assembly->image) &&
+ !m->method->klass->generic_class) {
+ static guint32 method_table_idx = 0xffffff;
+ if (m->method->klass->wastypebuilder) {
+ /* we use the same token as the one that was assigned
+ * to the Methodbuilder.
+ * FIXME: do the equivalent for Fields.
+ */
+ token = m->method->token;
+ } else {
+ /*
+ * Each token should have a unique index, but the indexes are
+ * assigned by managed code, so we don't know about them. An
+ * easy solution is to count backwards...
+ */
+ method_table_idx --;
+ token = MONO_TOKEN_METHOD_DEF | method_table_idx;
+ }
+ } else {
+ token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
+ }
+ /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
+ } else if (strcmp (klass->name, "MonoField") == 0) {
+ MonoReflectionField *f = (MonoReflectionField *)obj;
+ if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
+ static guint32 field_table_idx = 0xffffff;
+ field_table_idx --;
+ token = MONO_TOKEN_FIELD_DEF | field_table_idx;
+ } else {
+ token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
+ }
+ /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
+ } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
+ MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
+ token = mono_image_get_array_token (assembly, m, error);
+ return_val_if_nok (error, 0);
+ } else if (strcmp (klass->name, "SignatureHelper") == 0) {
+ MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
+ token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
+ return_val_if_nok (error, 0);
+ } else if (strcmp (klass->name, "EnumBuilder") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_metadata_token_from_dor (
+ mono_image_typedef_or_ref (assembly, type));
+ } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
+ MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
+ token = mono_image_get_field_on_inst_token (assembly, f, error);
+ return_val_if_nok (error, 0);
+ } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
+ MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
+ token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
+ if (!mono_error_ok (error))
+ return 0;
+ } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
+ MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
+ token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
+ if (!mono_error_ok (error))
+ return 0;
+ } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
+ return_val_if_nok (error, 0);
+ token = mono_metadata_token_from_dor (
+ mono_image_typedef_or_ref (assembly, type));
+ } else {
+ g_error ("requested token for %s\n", klass->name);
+ }
+
+ if (register_token)
+ mono_image_register_token (assembly, token, obj);
+
+ return token;
+}
+
+
+#endif
+
+#ifndef DISABLE_REFLECTION_EMIT
+
+/*
+ * mono_reflection_dynimage_basic_init:
+ * @assembly: an assembly builder object
+ *
+ * Create the MonoImage that represents the assembly builder and setup some
+ * of the helper hash table and the basic metadata streams.
+ */
+void
+mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
+{
+ MonoError error;
+ MonoDynamicAssembly *assembly;
+ MonoDynamicImage *image;
+ MonoDomain *domain = mono_object_domain (assemblyb);
+
+ if (assemblyb->dynamic_assembly)
+ return;
+
+#if HAVE_BOEHM_GC
+ /* assembly->assembly.image might be GC allocated */
+ assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
+#else
+ assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
+#endif
+
+ mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
+
+ assembly->assembly.ref_count = 1;
+ assembly->assembly.dynamic = TRUE;
+ assembly->assembly.corlib_internal = assemblyb->corlib_internal;
+ assemblyb->assembly.assembly = (MonoAssembly*)assembly;
+ assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
+ if (assemblyb->culture) {
+ assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
+ } else
+ assembly->assembly.aname.culture = g_strdup ("");
+
+ if (assemblyb->version) {
+ char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
+ char **version = g_strsplit (vstr, ".", 4);
+ char **parts = version;
+ assembly->assembly.aname.major = atoi (*parts++);
+ assembly->assembly.aname.minor = atoi (*parts++);
+ assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
+ assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
+
+ g_strfreev (version);
+ g_free (vstr);
+ } else {
+ assembly->assembly.aname.major = 0;
+ assembly->assembly.aname.minor = 0;
+ assembly->assembly.aname.build = 0;
+ assembly->assembly.aname.revision = 0;
+ }
+
+ assembly->run = assemblyb->access != 2;
+ assembly->save = assemblyb->access != 1;
+ assembly->domain = domain;
+
+ char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
+ if (mono_error_set_pending_exception (&error))
+ return;
+ image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
+ image->initial_image = TRUE;
+ assembly->assembly.aname.name = image->image.name;
+ assembly->assembly.image = &image->image;
+ if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
+ /* -1 to correct for the trailing NULL byte */
+ if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
+ g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
+ }
+ memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
+ }
+
+ mono_domain_assemblies_lock (domain);
+ domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
+ mono_domain_assemblies_unlock (domain);
+
+ register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
+
+ mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
+
+ mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
+}
+
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+static gpointer
+register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
+{
+ CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
+}
+
+static gpointer
+register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
+{
+ CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
+}
+
+static gboolean
+image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
+{
+ MonoDynamicImage *image = moduleb->dynamic_image;
+ MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
+ mono_error_init (error);
+ if (!image) {
+ int module_count;
+ MonoImage **new_modules;
+ MonoImage *ass;
+ char *name, *fqname;
+ /*
+ * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
+ * we don't know which module it belongs to, since that is only
+ * determined at assembly save time.
+ */
+ /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
+ name = mono_string_to_utf8_checked (ab->name, error);
+ return_val_if_nok (error, FALSE);
+ fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
+ if (!is_ok (error)) {
+ g_free (name);
+ return FALSE;
+ }
+ image = mono_dynamic_image_create (ab->dynamic_assembly, name, fqname);
+
+ moduleb->module.image = &image->image;
+ moduleb->dynamic_image = image;
+ register_module (mono_object_domain (moduleb), moduleb, image);
+
+ /* register the module with the assembly */
+ ass = ab->dynamic_assembly->assembly.image;
+ module_count = ass->module_count;
+ new_modules = g_new0 (MonoImage *, module_count + 1);
+
+ if (ass->modules)
+ memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
+ new_modules [module_count] = &image->image;
+ mono_image_addref (&image->image);
+
+ g_free (ass->modules);
+ ass->modules = new_modules;
+ ass->module_count ++;
+ }
+ return TRUE;
+}
+
+static void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+ MonoError error;
+ (void) image_module_basic_init (moduleb, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+#endif
+
+static gboolean
+is_corlib_type (MonoClass *klass)
+{
+ return klass->image == mono_defaults.corlib;
+}
+
+#define check_corlib_type_cached(_class, _namespace, _name) do { \
+ static MonoClass *cached_class; \
+ if (cached_class) \
+ return cached_class == _class; \
+ if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
+ cached_class = _class; \
+ return TRUE; \
+ } \
+ return FALSE; \
+} while (0) \
+
+
+
+#ifndef DISABLE_REFLECTION_EMIT
+static gboolean
+is_sre_array (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
+}
+
+static gboolean
+is_sre_byref (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
+}
+
+static gboolean
+is_sre_pointer (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
+}
+
+static gboolean
+is_sre_generic_instance (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
+}
+
+static gboolean
+is_sre_type_builder (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
+}
+
+static gboolean
+is_sre_method_builder (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
+}
+
+gboolean
+mono_is_sre_ctor_builder (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
+}
+
+static gboolean
+is_sre_field_builder (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
+}
+
+gboolean
+mono_is_sre_method_on_tb_inst (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
+}
+
+gboolean
+mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
+}
+
+static MonoReflectionType*
+mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
+{
+ static MonoMethod *method_get_underlying_system_type = NULL;
+ MonoReflectionType *rt;
+ MonoMethod *usertype_method;
+
+ mono_error_init (error);
+
+ if (!method_get_underlying_system_type)
+ method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
+
+ usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
+
+ rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
+
+ return rt;
+}
+
+MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
+{
+ MonoClass *klass;
+ mono_error_init (error);
+
+ if (!ref)
+ return NULL;
+ if (ref->type)
+ return ref->type;
+
+ if (mono_reflection_is_usertype (ref)) {
+ ref = mono_reflection_type_get_underlying_system_type (ref, error);
+ if (ref == NULL || mono_reflection_is_usertype (ref) || !is_ok (error))
+ return NULL;
+ if (ref->type)
+ return ref->type;
+ }
+
+ klass = mono_object_class (ref);
+
+ if (is_sre_array (klass)) {
+ MonoType *res;
+ MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
+ MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
+ return_val_if_nok (error, NULL);
+ g_assert (base);
+ if (sre_array->rank == 0) //single dimentional array
+ res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
+ else
+ res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
+ sre_array->type.type = res;
+ return res;
+ } else if (is_sre_byref (klass)) {
+ MonoType *res;
+ MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
+ MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
+ return_val_if_nok (error, NULL);
+ g_assert (base);
+ res = &mono_class_from_mono_type (base)->this_arg;
+ sre_byref->type.type = res;
+ return res;
+ } else if (is_sre_pointer (klass)) {
+ MonoType *res;
+ MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
+ MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
+ return_val_if_nok (error, NULL);
+ g_assert (base);
+ res = &mono_ptr_class_get (base)->byval_arg;
+ sre_pointer->type.type = res;
+ return res;
+ } else if (is_sre_generic_instance (klass)) {
+ MonoType *res, **types;
+ MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
+ int i, count;
+
+ count = mono_array_length (gclass->type_arguments);
+ types = g_new0 (MonoType*, count);
+ for (i = 0; i < count; ++i) {
+ MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
+ types [i] = mono_reflection_type_get_handle (t, error);
+ if (!types[i] || !is_ok (error)) {
+ g_free (types);
+ return NULL;
+ }
+ }
+
+ res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
+ g_free (types);
+ g_assert (res);
+ gclass->type.type = res;
+ return res;
+ }
+
+ g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
+ return NULL;
+}
+
+void
+ves_icall_SymbolType_create_unmanaged_type (MonoReflectionType *type)
+{
+ MonoError error;
+ mono_reflection_type_get_handle (type, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+static gboolean
+reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
+{
+ MonoDomain *domain = mono_object_domain ((MonoObject*)type);
+ MonoClass *klass;
+
+ mono_error_init (error);
+
+ MonoType *res = mono_reflection_type_get_handle (type, error);
+
+ if (!res && is_ok (error)) {
+ mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
+ }
+ return_val_if_nok (error, FALSE);
+
+ klass = mono_class_from_mono_type (res);
+
+ mono_loader_lock (); /*same locking as mono_type_get_object_checked */
+ mono_domain_lock (domain);
+
+ if (!image_is_dynamic (klass->image)) {
+ mono_class_setup_supertypes (klass);
+ } else {
+ if (!domain->type_hash)
+ domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
+ (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
+ mono_g_hash_table_insert (domain->type_hash, res, type);
+ }
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+
+ return TRUE;
+}
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+ MonoError error;
+ (void) reflection_register_with_runtime (type, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
+static MonoMethodSignature*
+parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
+ MonoMethodSignature *sig;
+ int count, i;
+
+ mono_error_init (error);
+
+ count = parameters? mono_array_length (parameters): 0;
+
+ sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
+ sig->param_count = count;
+ sig->sentinelpos = -1; /* FIXME */
+ for (i = 0; i < count; ++i) {
+ sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
+ if (!is_ok (error)) {
+ image_g_free (image, sig);
+ return NULL;
+ }
+ }
+ return sig;
+}
+
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
+static MonoMethodSignature*
+ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ sig = parameters_to_signature (image, ctor->parameters, error);
+ return_val_if_nok (error, NULL);
+ sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ return sig;
+}
+
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
+static MonoMethodSignature*
+method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ sig = parameters_to_signature (image, method->parameters, error);
+ return_val_if_nok (error, NULL);
+ sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ if (method->rtype) {
+ sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
+ if (!is_ok (error)) {
+ image_g_free (image, sig);
+ return NULL;
+ }
+ } else {
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ }
+ sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
+ return sig;
+}
+
+static MonoMethodSignature*
+dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ sig = parameters_to_signature (NULL, method->parameters, error);
+ return_val_if_nok (error, NULL);
+ sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ if (method->rtype) {
+ sig->ret = mono_reflection_type_get_handle (method->rtype, error);
+ if (!is_ok (error)) {
+ g_free (sig);
+ return NULL;
+ }
+ } else {
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ }
+ sig->generic_param_count = 0;
+ return sig;
+}
+
+static void
+get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
+{
+ mono_error_init (error);
+ MonoClass *klass = mono_object_class (prop);
+ if (strcmp (klass->name, "PropertyBuilder") == 0) {
+ MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
+ *name = mono_string_to_utf8_checked (pb->name, error);
+ return_if_nok (error);
+ *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
+ } else {
+ MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
+ *name = g_strdup (p->property->name);
+ if (p->property->get)
+ *type = mono_method_signature (p->property->get)->ret;
+ else
+ *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
+ }
+}
+
+static void
+get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
+{
+ mono_error_init (error);
+ MonoClass *klass = mono_object_class (field);
+ if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
+ *name = mono_string_to_utf8_checked (fb->name, error);
+ return_if_nok (error);
+ *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ } else {
+ MonoReflectionField *f = (MonoReflectionField *)field;
+ *name = g_strdup (mono_field_get_name (f->field));
+ *type = f->field->type;
+ }
+}
+
+#else /* DISABLE_REFLECTION_EMIT */
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+ /* This is empty */
+}
+
+static gboolean
+is_sre_type_builder (MonoClass *klass)
+{
+ return FALSE;
+}
+
+static gboolean
+is_sre_generic_instance (MonoClass *klass)
+{
+ return FALSE;
+}
+
+gboolean
+mono_is_sre_ctor_builder (MonoClass *klass)
+{
+ return FALSE;
+}
+
+gboolean
+mono_is_sre_method_on_tb_inst (MonoClass *klass)
+{
+ return FALSE;
+}
+
+gboolean
+mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
+{
+ return FALSE;
+}
+
+void
+mono_reflection_init_type_builder_generics (MonoObject *type, MonoError *error)
+{
+ mono_error_init (error);
+}
+
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+
+static gboolean
+is_sr_mono_field (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoField");
+}
+
+gboolean
+mono_is_sr_mono_property (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
+}
+
+static gboolean
+is_sr_mono_method (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
+}
+
+gboolean
+mono_is_sr_mono_cmethod (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
+}
+
+static gboolean
+is_sr_mono_generic_method (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
+}
+
+static gboolean
+is_sr_mono_generic_cmethod (MonoClass *klass)
+{
+ check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
+}
+
+gboolean
+mono_class_is_reflection_method_or_constructor (MonoClass *klass)
+{
+ return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
+}
+
+gboolean
+mono_is_sre_type_builder (MonoClass *klass)
+{
+ return is_sre_type_builder (klass);
+}
+
+gboolean
+mono_is_sre_generic_instance (MonoClass *klass)
+{
+ return is_sre_generic_instance (klass);
+}
+
+
+
+/**
+ * encode_cattr_value:
+ * Encode a value in a custom attribute stream of bytes.
+ * The value to encode is either supplied as an object in argument val
+ * (valuetypes are boxed), or as a pointer to the data in the
+ * argument argval.
+ * @type represents the type of the value
+ * @buffer is the start of the buffer
+ * @p the current position in the buffer
+ * @buflen contains the size of the buffer and is used to return the new buffer size
+ * if this needs to be realloced.
+ * @retbuffer and @retp return the start and the position of the buffer
+ * @error set on error.
+ */
+static void
+encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
+{
+ MonoTypeEnum simple_type;
+
+ mono_error_init (error);
+ if ((p-buffer) + 10 >= *buflen) {
+ char *newbuf;
+ *buflen *= 2;
+ newbuf = (char *)g_realloc (buffer, *buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ if (!argval)
+ argval = ((char*)arg + sizeof (MonoObject));
+ simple_type = type->type;
+handle_enum:
+ switch (simple_type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ *p++ = *argval;
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ swap_with_size (p, argval, 2, 1);
+ p += 2;
+ break;
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_R4:
+ swap_with_size (p, argval, 4, 1);
+ p += 4;
+ break;
+ case MONO_TYPE_R8:
+ swap_with_size (p, argval, 8, 1);
+ p += 8;
+ break;
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ swap_with_size (p, argval, 8, 1);
+ p += 8;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ if (type->data.klass->enumtype) {
+ simple_type = mono_class_enum_basetype (type->data.klass)->type;
+ goto handle_enum;
+ } else {
+ g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
+ }
+ break;
+ case MONO_TYPE_STRING: {
+ char *str;
+ guint32 slen;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+ str = mono_string_to_utf8_checked ((MonoString*)arg, error);
+ return_if_nok (error);
+ slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= *buflen) {
+ char *newbuf;
+ *buflen *= 2;
+ *buflen += slen;
+ newbuf = (char *)g_realloc (buffer, *buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ g_free (str);
+ break;
+ }
+ case MONO_TYPE_CLASS: {
+ char *str;
+ guint32 slen;
+ MonoType *arg_type;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+handle_type:
+ arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
+ return_if_nok (error);
+
+ str = type_get_qualified_name (arg_type, NULL);
+ slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= *buflen) {
+ char *newbuf;
+ *buflen *= 2;
+ *buflen += slen;
+ newbuf = (char *)g_realloc (buffer, *buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ g_free (str);
+ break;
+ }
+ case MONO_TYPE_SZARRAY: {
+ int len, i;
+ MonoClass *eclass, *arg_eclass;
+
+ if (!arg) {
+ *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
+ break;
+ }
+ len = mono_array_length ((MonoArray*)arg);
+ *p++ = len & 0xff;
+ *p++ = (len >> 8) & 0xff;
+ *p++ = (len >> 16) & 0xff;
+ *p++ = (len >> 24) & 0xff;
+ *retp = p;
+ *retbuffer = buffer;
+ eclass = type->data.klass;
+ arg_eclass = mono_object_class (arg)->element_class;
+
+ if (!eclass) {
+ /* Happens when we are called from the MONO_TYPE_OBJECT case below */
+ eclass = mono_defaults.object_class;
+ }
+ if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
+ char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
+ int elsize = mono_class_array_element_size (arg_eclass);
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
+ return_if_nok (error);
+ elptr += elsize;
+ }
+ } else if (eclass->valuetype && arg_eclass->valuetype) {
+ char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
+ int elsize = mono_class_array_element_size (eclass);
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
+ return_if_nok (error);
+ elptr += elsize;
+ }
+ } else {
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
+ return_if_nok (error);
+ }
+ }
+ break;
+ }
+ case MONO_TYPE_OBJECT: {
+ MonoClass *klass;
+ char *str;
+ guint32 slen;
+
+ /*
+ * The parameter type is 'object' but the type of the actual
+ * argument is not. So we have to add type information to the blob
+ * too. This is completely undocumented in the spec.
+ */
+
+ if (arg == NULL) {
+ *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
+ *p++ = 0xFF;
+ break;
+ }
+
+ klass = mono_object_class (arg);
+
+ if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
+ *p++ = 0x50;
+ goto handle_type;
+ } else {
+ return_if_nok (error);
+ }
+
+ if (klass->enumtype) {
+ *p++ = 0x55;
+ } else if (klass == mono_defaults.string_class) {
+ simple_type = MONO_TYPE_STRING;
+ *p++ = 0x0E;
+ goto handle_enum;
+ } else if (klass->rank == 1) {
+ *p++ = 0x1D;
+ if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
+ /* See Partition II, Appendix B3 */
+ *p++ = 0x51;
+ else
+ *p++ = klass->element_class->byval_arg.type;
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
+ return_if_nok (error);
+ break;
+ } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
+ *p++ = simple_type = klass->byval_arg.type;
+ goto handle_enum;
+ } else {
+ g_error ("unhandled type in custom attr");
+ }
+ str = type_get_qualified_name (mono_class_get_type(klass), NULL);
+ slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= *buflen) {
+ char *newbuf;
+ *buflen *= 2;
+ *buflen += slen;
+ newbuf = (char *)g_realloc (buffer, *buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ g_free (str);
+ simple_type = mono_class_enum_basetype (klass)->type;
+ goto handle_enum;
+ }
+ default:
+ g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
+ }
+ *retp = p;
+ *retbuffer = buffer;
+}
+
+static void
+encode_field_or_prop_type (MonoType *type, char *p, char **retp)
+{
+ if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
+ char *str = type_get_qualified_name (type, NULL);
+ int slen = strlen (str);
+
+ *p++ = 0x55;
+ /*
+ * This seems to be optional...
+ * *p++ = 0x80;
+ */
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ g_free (str);
+ } else if (type->type == MONO_TYPE_OBJECT) {
+ *p++ = 0x51;
+ } else if (type->type == MONO_TYPE_CLASS) {
+ /* it should be a type: encode_cattr_value () has the check */
+ *p++ = 0x50;
+ } else {
+ mono_metadata_encode_value (type->type, p, &p);
+ if (type->type == MONO_TYPE_SZARRAY)
+ /* See the examples in Partition VI, Annex B */
+ encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
+ }
+
+ *retp = p;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static void
+encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
+{
+ int len;
+
+ mono_error_init (error);
+
+ /* Preallocate a large enough buffer */
+ if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
+ char *str = type_get_qualified_name (type, NULL);
+ len = strlen (str);
+ g_free (str);
+ } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
+ char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
+ len = strlen (str);
+ g_free (str);
+ } else {
+ len = 0;
+ }
+ len += strlen (name);
+
+ if ((p-buffer) + 20 + len >= *buflen) {
+ char *newbuf;
+ *buflen *= 2;
+ *buflen += len;
+ newbuf = (char *)g_realloc (buffer, *buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+
+ encode_field_or_prop_type (type, p, &p);
+
+ len = strlen (name);
+ mono_metadata_encode_value (len, p, &p);
+ memcpy (p, name, len);
+ p += len;
+ encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
+ return_if_nok (error);
+ *retp = p;
+ *retbuffer = buffer;
+}
+
+/**
+ * mono_reflection_get_custom_attrs_blob:
+ * @ctor: custom attribute constructor
+ * @ctorArgs: arguments o the constructor
+ * @properties:
+ * @propValues:
+ * @fields:
+ * @fieldValues:
+ *
+ * Creates the blob of data that needs to be saved in the metadata and that represents
+ * the custom attributed described by @ctor, @ctorArgs etc.
+ * Returns: a Byte array representing the blob of data.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
+ MonoError error;
+ MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
+
+/**
+ * mono_reflection_get_custom_attrs_blob_checked:
+ * @ctor: custom attribute constructor
+ * @ctorArgs: arguments o the constructor
+ * @properties:
+ * @propValues:
+ * @fields:
+ * @fieldValues:
+ * @error: set on error
+ *
+ * Creates the blob of data that needs to be saved in the metadata and that represents
+ * the custom attributed described by @ctor, @ctorArgs etc.
+ * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
+{
+ MonoArray *result = NULL;
+ MonoMethodSignature *sig;
+ MonoObject *arg;
+ char *buffer, *p;
+ guint32 buflen, i;
+
+ mono_error_init (error);
+
+ if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
+ /* sig is freed later so allocate it in the heap */
+ sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
+ if (!is_ok (error)) {
+ g_free (sig);
+ return NULL;
+ }
+ } else {
+ sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
+ }
+
+ g_assert (mono_array_length (ctorArgs) == sig->param_count);
+ buflen = 256;
+ p = buffer = (char *)g_malloc (buflen);
+ /* write the prolog */
+ *p++ = 1;
+ *p++ = 0;
+ for (i = 0; i < sig->param_count; ++i) {
+ arg = mono_array_get (ctorArgs, MonoObject*, i);
+ encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
+ if (!is_ok (error)) goto leave;
+ }
+ i = 0;
+ if (properties)
+ i += mono_array_length (properties);
+ if (fields)
+ i += mono_array_length (fields);
+ *p++ = i & 0xff;
+ *p++ = (i >> 8) & 0xff;
+ if (properties) {
+ MonoObject *prop;
+ for (i = 0; i < mono_array_length (properties); ++i) {
+ MonoType *ptype;
+ char *pname;
+
+ prop = (MonoObject *)mono_array_get (properties, gpointer, i);
+ get_prop_name_and_type (prop, &pname, &ptype, error);
+ if (!is_ok (error)) goto leave;
+ *p++ = 0x54; /* PROPERTY signature */
+ encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
+ g_free (pname);
+ if (!is_ok (error)) goto leave;
+ }
+ }
+
+ if (fields) {
+ MonoObject *field;
+ for (i = 0; i < mono_array_length (fields); ++i) {
+ MonoType *ftype;
+ char *fname;
+
+ field = (MonoObject *)mono_array_get (fields, gpointer, i);
+ get_field_name_and_type (field, &fname, &ftype, error);
+ if (!is_ok (error)) goto leave;
+ *p++ = 0x53; /* FIELD signature */
+ encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
+ g_free (fname);
+ if (!is_ok (error)) goto leave;
+ }
+ }
+
+ g_assert (p - buffer <= buflen);
+ buflen = p - buffer;
+ result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
+ if (!is_ok (error))
+ goto leave;
+ p = mono_array_addr (result, char, 0);
+ memcpy (p, buffer, buflen);
+leave:
+ g_free (buffer);
+ if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
+ g_free (sig);
+ return result;
+}
+
+/**
+ * reflection_setup_internal_class:
+ * @tb: a TypeBuilder object
+ * @error: set on error
+ *
+ * Creates a MonoClass that represents the TypeBuilder.
+ * This is a trick that lets us simplify a lot of reflection code
+ * (and will allow us to support Build and Run assemblies easier).
+ *
+ * Returns TRUE on success. On failure, returns FALSE and sets @error.
+ */
+static gboolean
+reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
+{
+ MonoClass *klass, *parent;
+
+ mono_error_init (error);
+
+ mono_loader_lock ();
+
+ if (tb->parent) {
+ MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
+ if (!is_ok (error)) {
+ mono_loader_unlock ();
+ return FALSE;
+ }
+ /* check so we can compile corlib correctly */
+ if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
+ /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
+ parent = parent_type->data.klass;
+ } else {
+ parent = mono_class_from_mono_type (parent_type);
+ }
+ } else {
+ parent = NULL;
+ }
+
+ /* the type has already being created: it means we just have to change the parent */
+ if (tb->type.type) {
+ klass = mono_class_from_mono_type (tb->type.type);
+ klass->parent = NULL;
+ /* fool mono_class_setup_parent */
+ klass->supertypes = NULL;
+ mono_class_setup_parent (klass, parent);
+ mono_class_setup_mono_type (klass);
+ mono_loader_unlock ();
+ return TRUE;
+ }
+
+ klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
+
+ klass->image = &tb->module->dynamic_image->image;
+
+ klass->inited = 1; /* we lie to the runtime */
+ klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
+ if (!is_ok (error))
+ goto failure;
+ klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
+ if (!is_ok (error))
+ goto failure;
+ klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
+ klass->flags = tb->attrs;
+
+ mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+
+ klass->element_class = klass;
+
+ if (mono_class_get_ref_info (klass) == NULL) {
+ mono_class_set_ref_info (klass, tb);
+
+ /* Put into cache so mono_class_get_checked () will find it.
+ Skip nested types as those should not be available on the global scope. */
+ if (!tb->nesting_type)
+ mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
+
+ /*
+ We must register all types as we cannot rely on the name_cache hashtable since we find the class
+ by performing a mono_class_get which does the full resolution.
+
+ Working around this semantics would require us to write a lot of code for no clear advantage.
+ */
+ mono_image_append_class_to_reflection_info_set (klass);
+ } else {
+ g_assert (mono_class_get_ref_info (klass) == tb);
+ }
+
+ mono_dynamic_image_register_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
+
+ if (parent != NULL) {
+ mono_class_setup_parent (klass, parent);
+ } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
+ const char *old_n = klass->name;
+ /* trick to get relative numbering right when compiling corlib */
+ klass->name = "BuildingObject";
+ mono_class_setup_parent (klass, mono_defaults.object_class);
+ klass->name = old_n;
+ }
+
+ if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
+ (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
+ (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
+ klass->instance_size = sizeof (MonoObject);
+ klass->size_inited = 1;
+ mono_class_setup_vtable_general (klass, NULL, 0, NULL);
+ }
+
+ mono_class_setup_mono_type (klass);
+
+ mono_class_setup_supertypes (klass);
+
+ /*
+ * FIXME: handle interfaces.
+ */
+
+ tb->type.type = &klass->byval_arg;
+
+ if (tb->nesting_type) {
+ g_assert (tb->nesting_type->type);
+ MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
+ if (!is_ok (error)) goto failure;
+ klass->nested_in = mono_class_from_mono_type (nesting_type);
+ }
+
+ /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
+
+ mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+
+ mono_loader_unlock ();
+ return TRUE;
+
+failure:
+ mono_loader_unlock ();
+ return FALSE;
+}
+
+/**
+ * ves_icall_TypeBuilder_setup_internal_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Creates a MonoClass that represents the TypeBuilder.
+ * This is a trick that lets us simplify a lot of reflection code
+ * (and will allow us to support Build and Run assemblies easier).
+ *
+ */
+void
+ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoError error;
+ (void) reflection_setup_internal_class (tb, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+/**
+ * mono_reflection_create_generic_class:
+ * @tb: a TypeBuilder object
+ * @error: set on error
+ *
+ * Creates the generic class after all generic parameters have been added.
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
+ */
+gboolean
+mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
+{
+
+ MonoClass *klass;
+ int count, i;
+
+ mono_error_init (error);
+
+ klass = mono_class_from_mono_type (tb->type.type);
+
+ count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
+
+ if (klass->generic_container || (count == 0))
+ return TRUE;
+
+ g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
+
+ klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+
+ klass->generic_container->owner.klass = klass;
+ klass->generic_container->type_argc = count;
+ klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
+
+ klass->is_generic = 1;
+
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
+ MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
+ return_val_if_nok (error, FALSE);
+ MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
+ klass->generic_container->type_params [i] = *param;
+ /*Make sure we are a diferent type instance */
+ klass->generic_container->type_params [i].param.owner = klass->generic_container;
+ klass->generic_container->type_params [i].info.pklass = NULL;
+ klass->generic_container->type_params [i].info.flags = gparam->attrs;
+
+ g_assert (klass->generic_container->type_params [i].param.owner);
+ }
+
+ klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
+ return TRUE;
+}
+
+static MonoMarshalSpec*
+mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
+ MonoReflectionMarshal *minfo, MonoError *error)
+{
+ MonoMarshalSpec *res;
+
+ mono_error_init (error);
+
+ res = image_g_new0 (image, MonoMarshalSpec, 1);
+ res->native = (MonoMarshalNative)minfo->type;
+
+ switch (minfo->type) {
+ case MONO_NATIVE_LPARRAY:
+ res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
+ if (minfo->has_size) {
+ res->data.array_data.param_num = minfo->param_num;
+ res->data.array_data.num_elem = minfo->count;
+ res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
+ }
+ else {
+ res->data.array_data.param_num = -1;
+ res->data.array_data.num_elem = -1;
+ res->data.array_data.elem_mult = -1;
+ }
+ break;
+
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ res->data.array_data.num_elem = minfo->count;
+ break;
+
+ case MONO_NATIVE_CUSTOM:
+ if (minfo->marshaltyperef) {
+ MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
+ if (!is_ok (error)) {
+ image_g_free (image, res);
+ return NULL;
+ }
+ res->data.custom_data.custom_name =
+ type_get_fully_qualified_name (marshaltyperef);
+ }
+ if (minfo->mcookie) {
+ res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
+ if (!is_ok (error)) {
+ image_g_free (image, res);
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}
+#endif /* !DISABLE_REFLECTION_EMIT */
+
+MonoReflectionMarshalAsAttribute*
+mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
+ MonoMarshalSpec *spec, MonoError *error)
+{
+ MonoReflectionType *rt;
+ MonoReflectionMarshalAsAttribute *minfo;
+ MonoType *mtype;
+
+ mono_error_init (error);
+
+ minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
+ if (!minfo)
+ return NULL;
+ minfo->utype = spec->native;
+
+ switch (minfo->utype) {
+ case MONO_NATIVE_LPARRAY:
+ minfo->array_subtype = spec->data.array_data.elem_type;
+ minfo->size_const = spec->data.array_data.num_elem;
+ if (spec->data.array_data.param_num != -1)
+ minfo->size_param_index = spec->data.array_data.param_num;
+ break;
+
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ minfo->size_const = spec->data.array_data.num_elem;
+ break;
+
+ case MONO_NATIVE_CUSTOM:
+ if (spec->data.custom_data.custom_name) {
+ mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
+ return_val_if_nok (error, NULL);
+
+ if (mtype) {
+ rt = mono_type_get_object_checked (domain, mtype, error);
+ if (!rt)
+ return NULL;
+
+ MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
+ }
+
+ MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
+ }
+ if (spec->data.custom_data.cookie)
+ MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
+ break;
+
+ default:
+ break;
+ }
+
+ return minfo;
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+static MonoMethod*
+reflection_methodbuilder_to_mono_method (MonoClass *klass,
+ ReflectionMethodBuilder *rmb,
+ MonoMethodSignature *sig,
+ MonoError *error)
+{
+ MonoMethod *m;
+ MonoMethodWrapper *wrapperm;
+ MonoMarshalSpec **specs;
+ MonoReflectionMethodAux *method_aux;
+ MonoImage *image;
+ gboolean dynamic;
+ int i;
+
+ mono_error_init (error);
+ /*
+ * Methods created using a MethodBuilder should have their memory allocated
+ * inside the image mempool, while dynamic methods should have their memory
+ * malloc'd.
+ */
+ dynamic = rmb->refs != NULL;
+ image = dynamic ? NULL : klass->image;
+
+ if (!dynamic)
+ g_assert (!klass->generic_class);
+
+ mono_loader_lock ();
+
+ if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
+ else
+ m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
+
+ wrapperm = (MonoMethodWrapper*)m;
+
+ m->dynamic = dynamic;
+ m->slot = -1;
+ m->flags = rmb->attrs;
+ m->iflags = rmb->iattrs;
+ m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
+ m->klass = klass;
+ m->signature = sig;
+ m->sre_method = TRUE;
+ m->skip_visibility = rmb->skip_visibility;
+ if (rmb->table_idx)
+ m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
+
+ if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+ if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
+ m->string_ctor = 1;
+
+ m->signature->pinvoke = 1;
+ } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ m->signature->pinvoke = 1;
+
+ method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
+
+ method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
+ mono_error_assert_ok (error);
+ method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
+ mono_error_assert_ok (error);
+
+ ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
+
+ if (image_is_dynamic (klass->image))
+ g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+
+ mono_loader_unlock ();
+
+ return m;
+ } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
+ !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
+ MonoMethodHeader *header;
+ guint32 code_size;
+ gint32 max_stack, i;
+ gint32 num_locals = 0;
+ gint32 num_clauses = 0;
+ guint8 *code;
+
+ if (rmb->ilgen) {
+ code = mono_array_addr (rmb->ilgen->code, guint8, 0);
+ code_size = rmb->ilgen->code_len;
+ max_stack = rmb->ilgen->max_stack;
+ num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
+ if (rmb->ilgen->ex_handlers)
+ num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
+ } else {
+ if (rmb->code) {
+ code = mono_array_addr (rmb->code, guint8, 0);
+ code_size = mono_array_length (rmb->code);
+ /* we probably need to run a verifier on the code... */
+ max_stack = 8;
+ }
+ else {
+ code = NULL;
+ code_size = 0;
+ max_stack = 8;
+ }
+ }
+
+ header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
+ header->code_size = code_size;
+ header->code = (const unsigned char *)image_g_malloc (image, code_size);
+ memcpy ((char*)header->code, code, code_size);
+ header->max_stack = max_stack;
+ header->init_locals = rmb->init_locals;
+ header->num_locals = num_locals;
+
+ for (i = 0; i < num_locals; ++i) {
+ MonoReflectionLocalBuilder *lb =
+ mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
+
+ header->locals [i] = image_g_new0 (image, MonoType, 1);
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
+ mono_error_assert_ok (error);
+ memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
+ }
+
+ header->num_clauses = num_clauses;
+ if (num_clauses) {
+ header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
+ rmb->ilgen, num_clauses, error);
+ mono_error_assert_ok (error);
+ }
+
+ wrapperm->header = header;
+ }
+
+ if (rmb->generic_params) {
+ int count = mono_array_length (rmb->generic_params);
+ MonoGenericContainer *container = rmb->generic_container;
+
+ g_assert (container);
+
+ container->type_argc = count;
+ container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
+ container->owner.method = m;
+ container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
+
+ m->is_generic = TRUE;
+ mono_method_set_generic_container (m, container);
+
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gp =
+ mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
+ MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
+ mono_error_assert_ok (error);
+ MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
+ container->type_params [i] = *param;
+ }
+
+ /*
+ * The method signature might have pointers to generic parameters that belong to other methods.
+ * This is a valid SRE case, but the resulting method signature must be encoded using the proper
+ * generic parameters.
+ */
+ for (i = 0; i < m->signature->param_count; ++i) {
+ MonoType *t = m->signature->params [i];
+ if (t->type == MONO_TYPE_MVAR) {
+ MonoGenericParam *gparam = t->data.generic_param;
+ if (gparam->num < count) {
+ m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
+ m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
+ }
+
+ }
+ }
+
+ if (klass->generic_container) {
+ container->parent = klass->generic_container;
+ container->context.class_inst = klass->generic_container->context.class_inst;
+ }
+ container->context.method_inst = mono_get_shared_generic_inst (container);
+ }
+
+ if (rmb->refs) {
+ MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
+ int i;
+ void **data;
+
+ m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
+
+ mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
+ data [0] = GUINT_TO_POINTER (rmb->nrefs);
+ for (i = 0; i < rmb->nrefs; ++i)
+ data [i + 1] = rmb->refs [i];
+ }
+
+ method_aux = NULL;
+
+ /* Parameter info */
+ if (rmb->pinfo) {
+ if (!method_aux)
+ method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
+ method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
+ for (i = 0; i <= m->signature->param_count; ++i) {
+ MonoReflectionParamBuilder *pb;
+ if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
+ if ((i > 0) && (pb->attrs)) {
+ /* Make a copy since it might point to a shared type structure */
+ m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
+ m->signature->params [i - 1]->attrs = pb->attrs;
+ }
+
+ if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
+ MonoDynamicImage *assembly;
+ guint32 idx, len;
+ MonoTypeEnum def_type;
+ char *p;
+ const char *p2;
+
+ if (!method_aux->param_defaults) {
+ method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
+ method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
+ }
+ assembly = (MonoDynamicImage*)klass->image;
+ idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
+ method_aux->param_default_types [i] = def_type;
+ memcpy ((gpointer)method_aux->param_defaults [i], p, len);
+ }
+
+ if (pb->name) {
+ method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
+ mono_error_assert_ok (error);
+ }
+ if (pb->cattrs) {
+ if (!method_aux->param_cattr)
+ method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
+ method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
+ }
+ }
+ }
+ }
+
+ /* Parameter marshalling */
+ specs = NULL;
+ if (rmb->pinfo)
+ for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
+ MonoReflectionParamBuilder *pb;
+ if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
+ if (pb->marshal_info) {
+ if (specs == NULL)
+ specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
+ specs [pb->position] =
+ mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
+ if (!is_ok (error)) {
+ mono_loader_unlock ();
+ image_g_free (image, specs);
+ /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
+ return NULL;
+ }
+ }
+ }
+ }
+ if (specs != NULL) {
+ if (!method_aux)
+ method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
+ method_aux->param_marshall = specs;
+ }
+
+ if (image_is_dynamic (klass->image) && method_aux)
+ g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+
+ mono_loader_unlock ();
+
+ return m;
+}
+
+static MonoMethod*
+ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ mono_loader_lock ();
+ g_assert (klass->image != NULL);
+ sig = ctor_builder_to_signature (klass->image, mb, error);
+ mono_loader_unlock ();
+ return_val_if_nok (error, NULL);
+
+ if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
+ return NULL;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
+ return_val_if_nok (error, NULL);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ /* If we are in a generic class, we might be called multiple times from inflate_method */
+ if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+
+ return mb->mhandle;
+}
+
+static MonoMethod*
+methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ mono_error_init (error);
+
+ mono_loader_lock ();
+ g_assert (klass->image != NULL);
+ sig = method_builder_to_signature (klass->image, mb, error);
+ mono_loader_unlock ();
+ return_val_if_nok (error, NULL);
+
+ if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
+ return NULL;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
+ return_val_if_nok (error, NULL);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ /* If we are in a generic class, we might be called multiple times from inflate_method */
+ if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+ return mb->mhandle;
+}
+
+static MonoClassField*
+fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
+{
+ MonoClassField *field;
+ MonoType *custom;
+
+ mono_error_init (error);
+
+ field = g_new0 (MonoClassField, 1);
+
+ field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
+ mono_error_assert_ok (error);
+ if (fb->attrs || fb->modreq || fb->modopt) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ if (!is_ok (error)) {
+ g_free (field);
+ return NULL;
+ }
+ field->type = mono_metadata_type_dup (NULL, type);
+ field->type->attrs = fb->attrs;
+
+ g_assert (image_is_dynamic (klass->image));
+ custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
+ g_free (field->type);
+ if (!is_ok (error)) {
+ g_free (field);
+ return NULL;
+ }
+ field->type = mono_metadata_type_dup (klass->image, custom);
+ g_free (custom);
+ } else {
+ field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ if (!is_ok (error)) {
+ g_free (field);
+ return NULL;
+ }
+ }
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
+
+ return field;
+}
+#endif
+
+#ifndef DISABLE_REFLECTION_EMIT
+
+static MonoMethod *
+inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
+{
+ MonoMethodInflated *imethod;
+ MonoGenericContext *context;
+ int i;
+
+ /*
+ * With generic code sharing the klass might not be inflated.
+ * This can happen because classes inflated with their own
+ * type arguments are "normalized" to the uninflated class.
+ */
+ if (!klass->generic_class)
+ return method;
+
+ context = mono_class_get_context (klass);
+
+ if (klass->method.count && klass->methods) {
+ /* Find the already created inflated method */
+ for (i = 0; i < klass->method.count; ++i) {
+ g_assert (klass->methods [i]->is_inflated);
+ if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
+ break;
+ }
+ g_assert (i < klass->method.count);
+ imethod = (MonoMethodInflated*)klass->methods [i];
+ } else {
+ MonoError error;
+ imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
+ mono_error_assert_ok (&error);
+ }
+
+ if (method->is_generic && image_is_dynamic (method->klass->image)) {
+ MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
+
+ mono_image_lock ((MonoImage*)image);
+ mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
+ mono_image_unlock ((MonoImage*)image);
+ }
+ return (MonoMethod *) imethod;
+}
+
+static MonoMethod *
+inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
+{
+ MonoMethod *method;
+ MonoClass *gklass;
+
+ mono_error_init (error);
+
+ MonoClass *type_class = mono_object_class (type);
+
+ if (is_sre_generic_instance (type_class)) {
+ MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
+ MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
+ return_val_if_nok (error, NULL);
+ gklass = mono_class_from_mono_type (generic_type);
+ } else if (is_sre_type_builder (type_class)) {
+ MonoType *t = mono_reflection_type_get_handle (type, error);
+ return_val_if_nok (error, NULL);
+ gklass = mono_class_from_mono_type (t);
+ } else if (type->type) {
+ gklass = mono_class_from_mono_type (type->type);
+ gklass = mono_class_get_generic_type_definition (gklass);
+ } else {
+ g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
+ }
+
+ if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
+ if (((MonoReflectionMethodBuilder*)obj)->mhandle)
+ method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
+ else {
+ method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
+ if (!method)
+ return NULL;
+ }
+ else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
+ method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
+ if (!method)
+ return NULL;
+ } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
+ method = ((MonoReflectionMethod *) obj)->method;
+ else {
+ method = NULL; /* prevent compiler warning */
+ g_error ("can't handle type %s", obj->vtable->klass->name);
+ }
+
+ MonoType *t = mono_reflection_type_get_handle (type, error);
+ return_val_if_nok (error, NULL);
+ return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
+}
+
+static void
+reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoError *error)
+{
+ MonoGenericClass *gclass;
+ MonoClass *klass, *gklass;
+ MonoType *gtype;
+
+ mono_error_init (error);
+
+ gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
+ return_if_nok (error);
+ klass = mono_class_from_mono_type (gtype);
+ g_assert (gtype->type == MONO_TYPE_GENERICINST);
+ gclass = gtype->data.generic_class;
+
+ if (!gclass->is_dynamic)
+ return;
+
+ gklass = gclass->container_class;
+ mono_class_init (gklass);
+
+ /* Mark this as needing synchronization with its generic container */
+ gclass->need_sync = TRUE;
+}
+
+void
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+{
+ MonoError error;
+ reflection_generic_class_initialize (type, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+/**
+ * fix_partial_generic_class:
+ * @klass: a generic instantiation MonoClass
+ * @error: set on error
+ *
+ * Assumes that the generic container of @klass has its vtable
+ * initialized, and updates the parent class, interfaces, methods and
+ * fields of @klass by inflating the types using the generic context.
+ *
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
+ */
+static gboolean
+fix_partial_generic_class (MonoClass *klass, MonoError *error)
+{
+ MonoClass *gklass = klass->generic_class->container_class;
+ int i;
+
+ mono_error_init (error);
+
+ if (klass->wastypebuilder)
+ return TRUE;
+
+ if (klass->parent != gklass->parent) {
+ MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
+ if (mono_error_ok (error)) {
+ MonoClass *parent = mono_class_from_mono_type (parent_type);
+ mono_metadata_free_type (parent_type);
+ if (parent != klass->parent) {
+ /*fool mono_class_setup_parent*/
+ klass->supertypes = NULL;
+ mono_class_setup_parent (klass, parent);
+ }
+ } else {
+ if (gklass->wastypebuilder)
+ klass->wastypebuilder = TRUE;
+ return FALSE;
+ }
+ }
+
+ if (!klass->generic_class->need_sync)
+ return TRUE;
+
+ if (klass->method.count != gklass->method.count) {
+ klass->method.count = gklass->method.count;
+ klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
+
+ for (i = 0; i < klass->method.count; i++) {
+ klass->methods [i] = mono_class_inflate_generic_method_full_checked (
+ gklass->methods [i], klass, mono_class_get_context (klass), error);
+ mono_error_assert_ok (error);
+ }
+ }
+
+ if (klass->interface_count && klass->interface_count != gklass->interface_count) {
+ klass->interface_count = gklass->interface_count;
+ klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
+ klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
+
+ for (i = 0; i < gklass->interface_count; ++i) {
+ MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
+ return_val_if_nok (error, FALSE);
+
+ klass->interfaces [i] = mono_class_from_mono_type (iface_type);
+ mono_metadata_free_type (iface_type);
+
+ if (!ensure_runtime_vtable (klass->interfaces [i], error))
+ return FALSE;
+ }
+ klass->interfaces_inited = 1;
+ }
+
+ if (klass->field.count != gklass->field.count) {
+ klass->field.count = gklass->field.count;
+ klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
+
+ for (i = 0; i < klass->field.count; i++) {
+ klass->fields [i] = gklass->fields [i];
+ klass->fields [i].parent = klass;
+ klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
+ return_val_if_nok (error, FALSE);
+ }
+ }
+
+ /*We can only finish with this klass once it's parent has as well*/
+ if (gklass->wastypebuilder)
+ klass->wastypebuilder = TRUE;
+ return TRUE;
+}
+
+/**
+ * ensure_generic_class_runtime_vtable:
+ * @klass a generic class
+ * @error set on error
+ *
+ * Ensures that the generic container of @klass has a vtable and
+ * returns TRUE on success. On error returns FALSE and sets @error.
+ */
+static gboolean
+ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
+{
+ MonoClass *gklass = klass->generic_class->container_class;
+
+ mono_error_init (error);
+
+ if (!ensure_runtime_vtable (gklass, error))
+ return FALSE;
+
+ return fix_partial_generic_class (klass, error);
+}
+
+/**
+ * ensure_runtime_vtable:
+ * @klass the class
+ * @error set on error
+ *
+ * Ensures that @klass has a vtable and returns TRUE on success. On
+ * error returns FALSE and sets @error.
+ */
+static gboolean
+ensure_runtime_vtable (MonoClass *klass, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ int i, num, j;
+
+ mono_error_init (error);
+
+ if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
+ return TRUE;
+ if (klass->parent)
+ if (!ensure_runtime_vtable (klass->parent, error))
+ return FALSE;
+
+ if (tb) {
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ num += tb->num_methods;
+ klass->method.count = num;
+ klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ for (i = 0; i < num; ++i) {
+ MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
+ if (!ctor)
+ return FALSE;
+ klass->methods [i] = ctor;
+ }
+ num = tb->num_methods;
+ j = i;
+ for (i = 0; i < num; ++i) {
+ MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
+ if (!meth)
+ return FALSE;
+ klass->methods [j++] = meth;
+ }
+
+ if (tb->interfaces) {
+ klass->interface_count = mono_array_length (tb->interfaces);
+ klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
+ for (i = 0; i < klass->interface_count; ++i) {
+ MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
+ return_val_if_nok (error, FALSE);
+ klass->interfaces [i] = mono_class_from_mono_type (iface);
+ if (!ensure_runtime_vtable (klass->interfaces [i], error))
+ return FALSE;
+ }
+ klass->interfaces_inited = 1;
+ }
+ } else if (klass->generic_class){
+ if (!ensure_generic_class_runtime_vtable (klass, error)) {
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return FALSE;
+ }
+ }
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ int slot_num = 0;
+ for (i = 0; i < klass->method.count; ++i) {
+ MonoMethod *im = klass->methods [i];
+ if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
+ im->slot = slot_num++;
+ }
+
+ klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
+ mono_class_setup_interface_offsets (klass);
+ mono_class_setup_interface_id (klass);
+ }
+
+ /*
+ * The generic vtable is needed even if image->run is not set since some
+ * runtime code like ves_icall_Type_GetMethodsByName depends on
+ * method->slot being defined.
+ */
+
+ /*
+ * tb->methods could not be freed since it is used for determining
+ * overrides during dynamic vtable construction.
+ */
+
+ return TRUE;
+}
+
+static MonoMethod*
+mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
+{
+ mono_error_init (error);
+ MonoClass *klass = mono_object_class (method);
+ if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
+ MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
+ return sr_method->method;
+ }
+ if (is_sre_method_builder (klass)) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
+ return mb->mhandle;
+ }
+ if (mono_is_sre_method_on_tb_inst (klass)) {
+ MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
+ MonoMethod *result;
+ /*FIXME move this to a proper method and unify with resolve_object*/
+ if (m->method_args) {
+ result = mono_reflection_method_on_tb_inst_get_handle (m, error);
+ } else {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+ return_val_if_nok (error, NULL);
+ MonoClass *inflated_klass = mono_class_from_mono_type (type);
+ MonoMethod *mono_method;
+
+ if (is_sre_method_builder (mono_object_class (m->mb)))
+ mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
+ else if (is_sr_mono_method (mono_object_class (m->mb)))
+ mono_method = ((MonoReflectionMethod *)m->mb)->method;
+ else
+ g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
+
+ result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
+ }
+ return result;
+ }
+
+ g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
+ return NULL;
+}
+
+void
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb;
+ int i, j, onum;
+ MonoReflectionMethod *m;
+
+ mono_error_init (error);
+ *overrides = NULL;
+ *num_overrides = 0;
+
+ g_assert (image_is_dynamic (klass->image));
+
+ if (!mono_class_get_ref_info (klass))
+ return;
+
+ g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
+
+ tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
+
+ onum = 0;
+ if (tb->methods) {
+ for (i = 0; i < tb->num_methods; ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_methods)
+ onum += mono_array_length (mb->override_methods);
+ }
+ }
+
+ if (onum) {
+ *overrides = g_new0 (MonoMethod*, onum * 2);
+
+ onum = 0;
+ for (i = 0; i < tb->num_methods; ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_methods) {
+ for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
+ m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
+
+ (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
+ return_if_nok (error);
+ (*overrides) [onum * 2 + 1] = mb->mhandle;
+
+ g_assert (mb->mhandle);
+
+ onum ++;
+ }
+ }
+ }
+ }
+
+ *num_overrides = onum;
+}
+
+static void
+typebuilder_setup_fields (MonoClass *klass, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ MonoReflectionFieldBuilder *fb;
+ MonoClassField *field;
+ MonoImage *image = klass->image;
+ const char *p, *p2;
+ int i;
+ guint32 len, idx, real_size = 0;
+
+ klass->field.count = tb->num_fields;
+ klass->field.first = 0;
+
+ mono_error_init (error);
+
+ if (tb->class_size) {
+ if ((tb->packing_size & 0xffffff00) != 0) {
+ char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+ return;
+ }
+ klass->packing_size = tb->packing_size;
+ real_size = klass->instance_size + tb->class_size;
+ }
+
+ if (!klass->field.count) {
+ klass->instance_size = MAX (klass->instance_size, real_size);
+ return;
+ }
+
+ klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
+ mono_class_alloc_ext (klass);
+ klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
+ /*
+ This is, guess what, a hack.
+ The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
+ On the static path no field class is resolved, only types are built. This is the right thing to do
+ but we suck.
+ Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
+ */
+ klass->size_inited = 1;
+
+ for (i = 0; i < klass->field.count; ++i) {
+ MonoArray *rva_data;
+ fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
+ field = &klass->fields [i];
+ field->name = mono_string_to_utf8_image (image, fb->name, error);
+ if (!mono_error_ok (error))
+ return;
+ if (fb->attrs) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ return_if_nok (error);
+ field->type = mono_metadata_type_dup (klass->image, type);
+ field->type->attrs = fb->attrs;
+ } else {
+ field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+ return_if_nok (error);
+ }
+
+ if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
+ char *base = mono_array_addr (rva_data, char, 0);
+ size_t size = mono_array_length (rva_data);
+ char *data = (char *)mono_image_alloc (klass->image, size);
+ memcpy (data, base, size);
+ klass->ext->field_def_values [i].data = data;
+ }
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ fb->handle = field;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+ klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
+ }
+ if (fb->def_value) {
+ MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
+ field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ idx = mono_dynimage_encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
+ memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
+ }
+ }
+
+ klass->instance_size = MAX (klass->instance_size, real_size);
+ mono_class_layout_fields (klass, klass->instance_size);
+}
+
+static void
+typebuilder_setup_properties (MonoClass *klass, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ MonoReflectionPropertyBuilder *pb;
+ MonoImage *image = klass->image;
+ MonoProperty *properties;
+ int i;
+
+ mono_error_init (error);
+
+ if (!klass->ext)
+ klass->ext = image_g_new0 (image, MonoClassExt, 1);
+
+ klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
+ klass->ext->property.first = 0;
+
+ properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
+ klass->ext->properties = properties;
+ for (i = 0; i < klass->ext->property.count; ++i) {
+ pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
+ properties [i].parent = klass;
+ properties [i].attrs = pb->attrs;
+ properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
+ if (!mono_error_ok (error))
+ return;
+ if (pb->get_method)
+ properties [i].get = pb->get_method->mhandle;
+ if (pb->set_method)
+ properties [i].set = pb->set_method->mhandle;
+
+ mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
+ if (pb->def_value) {
+ guint32 len, idx;
+ const char *p, *p2;
+ MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
+ if (!klass->ext->prop_def_values)
+ klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
+ properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
+ idx = mono_dynimage_encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
+ memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
+ }
+ }
+}
+
+static MonoReflectionEvent *
+reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
+{
+ mono_error_init (error);
+
+ MonoEvent *event = g_new0 (MonoEvent, 1);
+ MonoClass *klass;
+
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+ if (!is_ok (error)) {
+ g_free (event);
+ return NULL;
+ }
+ klass = mono_class_from_mono_type (type);
+
+ event->parent = klass;
+ event->attrs = eb->attrs;
+ event->name = mono_string_to_utf8_checked (eb->name, error);
+ if (!is_ok (error)) {
+ g_free (event);
+ return NULL;
+ }
+ if (eb->add_method)
+ event->add = eb->add_method->mhandle;
+ if (eb->remove_method)
+ event->remove = eb->remove_method->mhandle;
+ if (eb->raise_method)
+ event->raise = eb->raise_method->mhandle;
+
+#ifndef MONO_SMALL_CONFIG
+ if (eb->other_methods) {
+ int j;
+ event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
+ for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (eb->other_methods,
+ MonoReflectionMethodBuilder*, j);
+ event->other [j] = mb->mhandle;
+ }
+ }
+#endif
+
+ MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
+ if (!is_ok (error)) {
+#ifndef MONO_SMALL_CONFIG
+ g_free (event->other);
+#endif
+ g_free (event);
+ return NULL;
+ }
+ return ev_obj;
+}
+
+MonoReflectionEvent *
+ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+{
+ MonoError error;
+ MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+static void
+typebuilder_setup_events (MonoClass *klass, MonoError *error)
+{
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+ MonoReflectionEventBuilder *eb;
+ MonoImage *image = klass->image;
+ MonoEvent *events;
+ int i;
+
+ mono_error_init (error);
+
+ if (!klass->ext)
+ klass->ext = image_g_new0 (image, MonoClassExt, 1);
+
+ klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
+ klass->ext->event.first = 0;
+
+ events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
+ klass->ext->events = events;
+ for (i = 0; i < klass->ext->event.count; ++i) {
+ eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
+ events [i].parent = klass;
+ events [i].attrs = eb->attrs;
+ events [i].name = mono_string_to_utf8_image (image, eb->name, error);
+ if (!mono_error_ok (error))
+ return;
+ if (eb->add_method)
+ events [i].add = eb->add_method->mhandle;
+ if (eb->remove_method)
+ events [i].remove = eb->remove_method->mhandle;
+ if (eb->raise_method)
+ events [i].raise = eb->raise_method->mhandle;
+
+#ifndef MONO_SMALL_CONFIG
+ if (eb->other_methods) {
+ int j;
+ events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
+ for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (eb->other_methods,
+ MonoReflectionMethodBuilder*, j);
+ events [i].other [j] = mb->mhandle;
+ }
+ }
+#endif
+ mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
+ }
+}
+
+struct remove_instantiations_user_data
+{
+ MonoClass *klass;
+ MonoError *error;
+};
+
+static gboolean
+remove_instantiations_of_and_ensure_contents (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
+ MonoType *type = (MonoType*)key;
+ MonoClass *klass = data->klass;
+ gboolean already_failed = !is_ok (data->error);
+ MonoError lerror;
+ MonoError *error = already_failed ? &lerror : data->error;
+
+ if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
+ MonoClass *inst_klass = mono_class_from_mono_type (type);
+ //Ensure it's safe to use it.
+ if (!fix_partial_generic_class (inst_klass, error)) {
+ mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ // Marked the class with failure, but since some other instantiation already failed,
+ // just report that one, and swallow the error from this one.
+ if (already_failed)
+ mono_error_cleanup (error);
+ }
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+MonoReflectionType*
+ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoError error;
+ MonoClass *klass;
+ MonoDomain* domain;
+ MonoReflectionType* res;
+ int i;
+
+ mono_error_init (&error);
+
+ domain = mono_object_domain (tb);
+ klass = mono_class_from_mono_type (tb->type.type);
+
+ mono_save_custom_attrs (klass->image, klass, tb->cattrs);
+
+ /*
+ * we need to lock the domain because the lock will be taken inside
+ * So, we need to keep the locking order correct.
+ */
+ mono_loader_lock ();
+ mono_domain_lock (domain);
+ if (klass->wastypebuilder) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+
+ res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
+ mono_error_set_pending_exception (&error);
+
+ return res;
+ }
+ /*
+ * Fields to set in klass:
+ * the various flags: delegate/unicode/contextbound etc.
+ */
+ klass->flags = tb->attrs;
+ klass->has_cctor = 1;
+
+ mono_class_setup_parent (klass, klass->parent);
+ /* fool mono_class_setup_supertypes */
+ klass->supertypes = NULL;
+ mono_class_setup_supertypes (klass);
+ mono_class_setup_mono_type (klass);
+
+#if 0
+ if (!((MonoDynamicImage*)klass->image)->run) {
+ if (klass->generic_container) {
+ /* FIXME: The code below can't handle generic classes */
+ klass->wastypebuilder = TRUE;
+ mono_loader_unlock ();
+ mono_domain_unlock (domain);
+
+ res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
+ mono_error_set_pending_exception (&error);
+
+ return res;
+ }
+ }
+#endif
+
+ /* enums are done right away */
+ if (!klass->enumtype)
+ if (!ensure_runtime_vtable (klass, &error))
+ goto failure;
+
+ if (tb->subtypes) {
+ for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
+ MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
+ mono_class_alloc_ext (klass);
+ MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
+ if (!is_ok (&error)) goto failure;
+ klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
+ }
+ }
+
+ klass->nested_classes_inited = TRUE;
+
+ /* fields and object layout */
+ if (klass->parent) {
+ if (!klass->parent->size_inited)
+ mono_class_init (klass->parent);
+ klass->instance_size = klass->parent->instance_size;
+ klass->sizes.class_size = 0;
+ klass->min_align = klass->parent->min_align;
+ /* if the type has no fields we won't call the field_setup
+ * routine which sets up klass->has_references.
+ */
+ klass->has_references |= klass->parent->has_references;
+ } else {
+ klass->instance_size = sizeof (MonoObject);
+ klass->min_align = 1;
+ }
+
+ /* FIXME: handle packing_size and instance_size */
+ typebuilder_setup_fields (klass, &error);
+ if (!mono_error_ok (&error))
+ goto failure;
+ typebuilder_setup_properties (klass, &error);
+ if (!mono_error_ok (&error))
+ goto failure;
+
+ typebuilder_setup_events (klass, &error);
+ if (!mono_error_ok (&error))
+ goto failure;
+
+ klass->wastypebuilder = TRUE;
+
+ /*
+ * If we are a generic TypeBuilder, there might be instantiations in the type cache
+ * which have type System.Reflection.MonoGenericClass, but after the type is created,
+ * we want to return normal System.MonoType objects, so clear these out from the cache.
+ *
+ * Together with this we must ensure the contents of all instances to match the created type.
+ */
+ if (domain->type_hash && klass->generic_container) {
+ struct remove_instantiations_user_data data;
+ data.klass = klass;
+ data.error = &error;
+ mono_error_assert_ok (&error);
+ mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
+ if (!is_ok (&error))
+ goto failure;
+ }
+
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+
+ if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
+ goto failure_unlocked;
+ }
+
+ res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
+ if (!is_ok (&error))
+ goto failure_unlocked;
+
+ g_assert (res != (MonoReflectionType*)tb);
+
+ return res;
+
+failure:
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ klass->wastypebuilder = TRUE;
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+failure_unlocked:
+ mono_error_set_pending_exception (&error);
+ return NULL;
+}
+
+static gboolean
+reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
+{
+ MonoGenericParamFull *param;
+ MonoImage *image;
+ MonoClass *pklass;
+
+ mono_error_init (error);
+
+ image = &gparam->tbuilder->module->dynamic_image->image;
+
+ param = mono_image_new0 (image, MonoGenericParamFull, 1);
+
+ param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
+ mono_error_assert_ok (error);
+ param->param.num = gparam->index;
+
+ if (gparam->mbuilder) {
+ if (!gparam->mbuilder->generic_container) {
+ MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
+ return_val_if_nok (error, FALSE);
+
+ MonoClass *klass = mono_class_from_mono_type (tb);
+ gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+ gparam->mbuilder->generic_container->is_method = TRUE;
+ /*
+ * Cannot set owner.method, since the MonoMethod is not created yet.
+ * Set the image field instead, so type_in_image () works.
+ */
+ gparam->mbuilder->generic_container->is_anonymous = TRUE;
+ gparam->mbuilder->generic_container->owner.image = klass->image;
+ }
+ param->param.owner = gparam->mbuilder->generic_container;
+ } else if (gparam->tbuilder) {
+ if (!gparam->tbuilder->generic_container) {
+ MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
+ return_val_if_nok (error, FALSE);
+ MonoClass *klass = mono_class_from_mono_type (tb);
+ gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+ gparam->tbuilder->generic_container->owner.klass = klass;
+ }
+ param->param.owner = gparam->tbuilder->generic_container;
+ }
+
+ pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
+
+ gparam->type.type = &pklass->byval_arg;
+
+ mono_class_set_ref_info (pklass, gparam);
+ mono_image_append_class_to_reflection_info_set (pklass);
+
+ return TRUE;
+}
+
+void
+ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+{
+ MonoError error;
+ (void) reflection_initialize_generic_parameter (gparam, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+
+typedef struct {
+ MonoMethod *handle;
+ MonoDomain *domain;
+} DynamicMethodReleaseData;
+
+/*
+ * The runtime automatically clean up those after finalization.
+*/
+static MonoReferenceQueue *dynamic_method_queue;
+
+static void
+free_dynamic_method (void *dynamic_method)
+{
+ DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
+ MonoDomain *domain = data->domain;
+ MonoMethod *method = data->handle;
+ guint32 dis_link;
+
+ mono_domain_lock (domain);
+ dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
+ g_hash_table_remove (domain->method_to_dyn_method, method);
+ mono_domain_unlock (domain);
+ g_assert (dis_link);
+ mono_gchandle_free (dis_link);
+
+ mono_runtime_free_method (domain, method);
+ g_free (data);
+}
+
+static gboolean
+reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
+{
+ MonoReferenceQueue *queue;
+ MonoMethod *handle;
+ DynamicMethodReleaseData *release_data;
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+ MonoClass *klass;
+ MonoDomain *domain;
+ GSList *l;
+ int i;
+
+ mono_error_init (error);
+
+ if (mono_runtime_is_shutting_down ()) {
+ mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
+ return FALSE;
+ }
+
+ if (!(queue = dynamic_method_queue)) {
+ mono_loader_lock ();
+ if (!(queue = dynamic_method_queue))
+ queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
+ mono_loader_unlock ();
+ }
+
+ sig = dynamic_method_to_signature (mb, error);
+ return_val_if_nok (error, FALSE);
+
+ reflection_methodbuilder_from_dynamic_method (&rmb, mb);
+
+ /*
+ * Resolve references.
+ */
+ /*
+ * Every second entry in the refs array is reserved for storing handle_class,
+ * which is needed by the ldtoken implementation in the JIT.
+ */
+ rmb.nrefs = mb->nrefs;
+ rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
+ for (i = 0; i < mb->nrefs; i += 2) {
+ MonoClass *handle_class;
+ gpointer ref;
+ MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
+
+ if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
+ MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
+ /*
+ * The referenced DynamicMethod should already be created by the managed
+ * code, except in the case of circular references. In that case, we store
+ * method in the refs array, and fix it up later when the referenced
+ * DynamicMethod is created.
+ */
+ if (method->mhandle) {
+ ref = method->mhandle;
+ } else {
+ /* FIXME: GC object stored in unmanaged memory */
+ ref = method;
+
+ /* FIXME: GC object stored in unmanaged memory */
+ method->referenced_by = g_slist_append (method->referenced_by, mb);
+ }
+ handle_class = mono_defaults.methodhandle_class;
+ } else {
+ MonoException *ex = NULL;
+ ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
+ if (!is_ok (error)) {
+ g_free (rmb.refs);
+ return FALSE;
+ }
+ if (!ref)
+ ex = mono_get_exception_type_load (NULL, NULL);
+ else if (mono_security_core_clr_enabled ())
+ ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
+
+ if (ex) {
+ g_free (rmb.refs);
+ mono_error_set_exception_instance (error, ex);
+ return FALSE;
+ }
+ }
+
+ rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
+ rmb.refs [i + 1] = handle_class;
+ }
+
+ if (mb->owner) {
+ MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
+ if (!is_ok (error)) {
+ g_free (rmb.refs);
+ return FALSE;
+ }
+ klass = mono_class_from_mono_type (owner_type);
+ } else {
+ klass = mono_defaults.object_class;
+ }
+
+ mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
+ g_free (rmb.refs);
+ return_val_if_nok (error, FALSE);
+
+ release_data = g_new (DynamicMethodReleaseData, 1);
+ release_data->handle = handle;
+ release_data->domain = mono_object_get_domain ((MonoObject*)mb);
+ if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
+ g_free (release_data);
+
+ /* Fix up refs entries pointing at us */
+ for (l = mb->referenced_by; l; l = l->next) {
+ MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
+ MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
+ gpointer *data;
+
+ g_assert (method->mhandle);
+
+ data = (gpointer*)wrapper->method_data;
+ for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
+ if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
+ data [i + 1] = mb->mhandle;
+ }
+ }
+ g_slist_free (mb->referenced_by);
+
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+
+ domain = mono_domain_get ();
+ mono_domain_lock (domain);
+ if (!domain->method_to_dyn_method)
+ domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
+ mono_domain_unlock (domain);
+
+ return TRUE;
+}
+
+void
+ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+ MonoError error;
+ (void) reflection_create_dynamic_method (mb, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+#endif /* DISABLE_REFLECTION_EMIT */
+
+MonoMethodSignature *
+mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
+{
+ MonoMethodSignature *sig;
+ g_assert (image_is_dynamic (image));
+
+ mono_error_init (error);
+
+ sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
+ if (sig)
+ return sig;
+
+ return mono_method_signature_checked (method, error);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+
+/*
+ * ensure_complete_type:
+ *
+ * Ensure that KLASS is completed if it is a dynamic type, or references
+ * dynamic types.
+ */
+static void
+ensure_complete_type (MonoClass *klass, MonoError *error)
+{
+ mono_error_init (error);
+
+ if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
+
+ mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+ return_if_nok (error);
+
+ // Asserting here could break a lot of code
+ //g_assert (klass->wastypebuilder);
+ }
+
+ if (klass->generic_class) {
+ MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ int i;
+
+ for (i = 0; i < inst->type_argc; ++i) {
+ ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
+ return_if_nok (error);
+ }
+ }
+}
+
+gpointer
+mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+{
+ gpointer result = NULL;
+
+ mono_error_init (error);
+
+ if (strcmp (obj->vtable->klass->name, "String") == 0) {
+ result = mono_string_intern_checked ((MonoString*)obj, error);
+ return_val_if_nok (error, NULL);
+ *handle_class = mono_defaults.string_class;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+ return_val_if_nok (error, NULL);
+ MonoClass *mc = mono_class_from_mono_type (type);
+ if (!mono_class_init (mc)) {
+ mono_error_set_for_class_failure (error, mc);
+ return NULL;
+ }
+
+ if (context) {
+ MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+ return_val_if_nok (error, NULL);
+
+ result = mono_class_from_mono_type (inflated);
+ mono_metadata_free_type (inflated);
+ } else {
+ result = mono_class_from_mono_type (type);
+ }
+ *handle_class = mono_defaults.typehandle_class;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
+ strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
+ strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
+ strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
+ result = ((MonoReflectionMethod*)obj)->method;
+ if (context) {
+ result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+ mono_error_assert_ok (error);
+ }
+ *handle_class = mono_defaults.methodhandle_class;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
+ result = mb->mhandle;
+ if (!result) {
+ /* Type is not yet created */
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
+
+ mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+ return_val_if_nok (error, NULL);
+
+ /*
+ * Hopefully this has been filled in by calling CreateType() on the
+ * TypeBuilder.
+ */
+ /*
+ * TODO: This won't work if the application finishes another
+ * TypeBuilder instance instead of this one.
+ */
+ result = mb->mhandle;
+ }
+ if (context) {
+ result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+ mono_error_assert_ok (error);
+ }
+ *handle_class = mono_defaults.methodhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
+
+ result = cb->mhandle;
+ if (!result) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
+
+ mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+ return_val_if_nok (error, NULL);
+ result = cb->mhandle;
+ }
+ if (context) {
+ result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+ mono_error_assert_ok (error);
+ }
+ *handle_class = mono_defaults.methodhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
+ MonoClassField *field = ((MonoReflectionField*)obj)->field;
+
+ ensure_complete_type (field->parent, error);
+ return_val_if_nok (error, NULL);
+
+ if (context) {
+ MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
+ return_val_if_nok (error, NULL);
+
+ MonoClass *klass = mono_class_from_mono_type (inflated);
+ MonoClassField *inflated_field;
+ gpointer iter = NULL;
+ mono_metadata_free_type (inflated);
+ while ((inflated_field = mono_class_get_fields (klass, &iter))) {
+ if (!strcmp (field->name, inflated_field->name))
+ break;
+ }
+ g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
+ result = inflated_field;
+ } else {
+ result = field;
+ }
+ *handle_class = mono_defaults.fieldhandle_class;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
+ result = fb->handle;
+
+ if (!result) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
+
+ mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+ return_val_if_nok (error, NULL);
+ result = fb->handle;
+ }
+
+ if (fb->handle && fb->handle->parent->generic_container) {
+ MonoClass *klass = fb->handle->parent;
+ MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
+ return_val_if_nok (error, NULL);
+
+ MonoClass *inflated = mono_class_from_mono_type (type);
+
+ result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
+ g_assert (result);
+ mono_metadata_free_type (type);
+ }
+ *handle_class = mono_defaults.fieldhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+ return_val_if_nok (error, NULL);
+ MonoClass *klass;
+
+ klass = type->data.klass;
+ if (klass->wastypebuilder) {
+ /* Already created */
+ result = klass;
+ }
+ else {
+ mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+ return_val_if_nok (error, NULL);
+ result = type->data.klass;
+ g_assert (result);
+ }
+ *handle_class = mono_defaults.typehandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
+ MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
+ MonoMethodSignature *sig;
+ int nargs, i;
+
+ if (helper->arguments)
+ nargs = mono_array_length (helper->arguments);
+ else
+ nargs = 0;
+
+ sig = mono_metadata_signature_alloc (image, nargs);
+ sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
+ sig->hasthis = helper->call_conv & 32 ? 1 : 0;
+
+ if (helper->unmanaged_call_conv) { /* unmanaged */
+ sig->call_convention = helper->unmanaged_call_conv - 1;
+ sig->pinvoke = TRUE;
+ } else if (helper->call_conv & 0x02) {
+ sig->call_convention = MONO_CALL_VARARG;
+ } else {
+ sig->call_convention = MONO_CALL_DEFAULT;
+ }
+
+ sig->param_count = nargs;
+ /* TODO: Copy type ? */
+ sig->ret = helper->return_type->type;
+ for (i = 0; i < nargs; ++i) {
+ sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
+ if (!is_ok (error)) {
+ image_g_free (image, sig);
+ return NULL;
+ }
+ }
+
+ result = sig;
+ *handle_class = NULL;
+ } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
+ MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
+ /* Already created by the managed code */
+ g_assert (method->mhandle);
+ result = method->mhandle;
+ *handle_class = mono_defaults.methodhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+ return_val_if_nok (error, NULL);
+ type = mono_class_inflate_generic_type_checked (type, context, error);
+ return_val_if_nok (error, NULL);
+
+ result = mono_class_from_mono_type (type);
+ *handle_class = mono_defaults.typehandle_class;
+ g_assert (result);
+ mono_metadata_free_type (type);
+ } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+ return_val_if_nok (error, NULL);
+ type = mono_class_inflate_generic_type_checked (type, context, error);
+ return_val_if_nok (error, NULL);
+
+ result = mono_class_from_mono_type (type);
+ *handle_class = mono_defaults.typehandle_class;
+ g_assert (result);
+ mono_metadata_free_type (type);
+ } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
+ MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
+ MonoClass *inflated;
+ MonoType *type;
+ MonoClassField *field;
+
+ if (is_sre_field_builder (mono_object_class (f->fb)))
+ field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
+ else if (is_sr_mono_field (mono_object_class (f->fb)))
+ field = ((MonoReflectionField*)f->fb)->field;
+ else
+ g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
+
+ MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
+ return_val_if_nok (error, NULL);
+ type = mono_class_inflate_generic_type_checked (finst, context, error);
+ return_val_if_nok (error, NULL);
+
+ inflated = mono_class_from_mono_type (type);
+
+ result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
+ ensure_complete_type (field->parent, error);
+ if (!is_ok (error)) {
+ mono_metadata_free_type (type);
+ return NULL;
+ }
+
+ g_assert (result);
+ mono_metadata_free_type (type);
+ *handle_class = mono_defaults.fieldhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
+ MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
+ MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
+ return_val_if_nok (error, NULL);
+ MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
+ return_val_if_nok (error, NULL);
+
+ MonoClass *inflated_klass = mono_class_from_mono_type (type);
+ MonoMethod *method;
+
+ if (mono_is_sre_ctor_builder (mono_object_class (c->cb)))
+ method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
+ else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb)))
+ method = ((MonoReflectionMethod *)c->cb)->method;
+ else
+ g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
+
+ result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
+ *handle_class = mono_defaults.methodhandle_class;
+ mono_metadata_free_type (type);
+ } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
+ MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
+ if (m->method_args) {
+ result = mono_reflection_method_on_tb_inst_get_handle (m, error);
+ return_val_if_nok (error, NULL);
+ if (context) {
+ result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+ mono_error_assert_ok (error);
+ }
+ } else {
+ MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+ return_val_if_nok (error, NULL);
+ MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
+ return_val_if_nok (error, NULL);
+
+ MonoClass *inflated_klass = mono_class_from_mono_type (type);
+ MonoMethod *method;
+
+ if (is_sre_method_builder (mono_object_class (m->mb)))
+ method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
+ else if (is_sr_mono_method (mono_object_class (m->mb)))
+ method = ((MonoReflectionMethod *)m->mb)->method;
+ else
+ g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
+
+ result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
+ mono_metadata_free_type (type);
+ }
+ *handle_class = mono_defaults.methodhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
+ MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
+ MonoType *mtype;
+ MonoClass *klass;
+ MonoMethod *method;
+ gpointer iter;
+ char *name;
+
+ mtype = mono_reflection_type_get_handle (m->parent, error);
+ return_val_if_nok (error, NULL);
+ klass = mono_class_from_mono_type (mtype);
+
+ /* Find the method */
+
+ name = mono_string_to_utf8_checked (m->name, error);
+ return_val_if_nok (error, NULL);
+ iter = NULL;
+ while ((method = mono_class_get_methods (klass, &iter))) {
+ if (!strcmp (method->name, name))
+ break;
+ }
+ g_free (name);
+
+ // FIXME:
+ g_assert (method);
+ // FIXME: Check parameters/return value etc. match
+
+ result = method;
+ *handle_class = mono_defaults.methodhandle_class;
+ } else if (is_sre_array (mono_object_get_class(obj)) ||
+ is_sre_byref (mono_object_get_class(obj)) ||
+ is_sre_pointer (mono_object_get_class(obj))) {
+ MonoReflectionType *ref_type = (MonoReflectionType *)obj;
+ MonoType *type = mono_reflection_type_get_handle (ref_type, error);
+ return_val_if_nok (error, NULL);
+
+ if (context) {
+ MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+ return_val_if_nok (error, NULL);
+
+ result = mono_class_from_mono_type (inflated);
+ mono_metadata_free_type (inflated);
+ } else {
+ result = mono_class_from_mono_type (type);
+ }
+ *handle_class = mono_defaults.typehandle_class;
+ } else {
+ g_print ("%s\n", obj->vtable->klass->name);
+ g_assert_not_reached ();
+ }
+ return result;
+}
+
+#else /* DISABLE_REFLECTION_EMIT */
+
+MonoArray*
+mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+void
+ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
+{
+ g_assert_not_reached ();
+}
+
+gboolean
+mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
+{
+ g_assert_not_reached ();
+ return FALSE;
+}
+
+void
+mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
+{
+ g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
+}
+
+static void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+ g_assert_not_reached ();
+}
+
+guint32
+mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+
+guint32
+mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+
+guint32
+mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
+ gboolean create_open_instance, gboolean register_token, MonoError *error)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+
+void
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+{
+ g_assert_not_reached ();
+}
+
+void
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
+{
+ mono_error_init (error);
+ *overrides = NULL;
+ *num_overrides = 0;
+}
+
+MonoReflectionEvent *
+ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+MonoReflectionType*
+ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+void
+ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+{
+ g_assert_not_reached ();
+}
+
+void
+ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+}
+
+MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
+{
+ mono_error_init (error);
+ if (!ref)
+ return NULL;
+ return ref->type;
+}
+
+#endif /* DISABLE_REFLECTION_EMIT */
+
+#ifndef DISABLE_REFLECTION_EMIT
+MonoMethod*
+mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error)
+{
+ MonoType *tb;
+ MonoClass *klass;
+
+ tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
+ return_val_if_nok (error, NULL);
+ klass = mono_class_from_mono_type (tb);
+
+ return methodbuilder_to_mono_method (klass, mb, error);
+}
+#else /* DISABLE_REFLECTION_EMIT */
+MonoMethod*
+mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+#endif /* DISABLE_REFLECTION_EMIT */
+
+gint32
+ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
+{
+ MONO_CHECK_ARG_NULL (obj, 0);
+
+ MonoError error;
+ gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+gint32
+ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
+ MonoReflectionMethod *method,
+ MonoArray *opt_param_types)
+{
+ MONO_CHECK_ARG_NULL (method, 0);
+
+ MonoError error;
+ gint32 result = mono_image_create_method_token (
+ mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+void
+ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
+{
+ MonoError error;
+ mono_image_create_pefile (mb, file, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+void
+ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
+{
+ MonoError error;
+ mono_image_build_metadata (mb, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+void
+ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
+{
+ mono_image_register_token (mb->dynamic_image, token, obj);
+}
+
+MonoObject*
+ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
+{
+ MonoObject *obj;
+
+ mono_loader_lock ();
+ obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
+ mono_loader_unlock ();
+
+ return obj;
+}
+
+/**
+ * ves_icall_TypeBuilder_create_generic_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Creates the generic class after all generic parameters have been added.
+ */
+void
+ves_icall_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoError error;
+ (void) mono_reflection_create_generic_class (tb, &error);
+ mono_error_set_pending_exception (&error);
+}
+
+#ifndef DISABLE_REFLECTION_EMIT
+MonoArray*
+ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
+ MonoError error;
+ MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+#endif
+
+void
+ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
+{
+ mono_reflection_dynimage_basic_init (assemblyb);
+}
+
+MonoBoolean
+ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
+{
+ return mono_type_is_generic_parameter (tb->type.type);
+}
+
+void
+ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
+ MonoReflectionType *t)
+{
+ enumtype->type = t->type;
+}
+
+MonoReflectionType*
+ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
+{
+ MonoError error;
+ MonoReflectionType *ret;
+ MonoClass *klass;
+ int isbyref = 0, rank;
+ char *p;
+ char *str = mono_string_to_utf8_checked (smodifiers, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ klass = mono_class_from_mono_type (tb->type.type);
+ p = str;
+ /* logic taken from mono_reflection_parse_type(): keep in sync */
+ while (*p) {
+ switch (*p) {
+ case '&':
+ if (isbyref) { /* only one level allowed by the spec */
+ g_free (str);
+ return NULL;
+ }
+ isbyref = 1;
+ p++;
+
+ g_free (str);
+
+ ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
+ mono_error_set_pending_exception (&error);
+
+ return ret;
+ case '*':
+ klass = mono_ptr_class_get (&klass->byval_arg);
+ mono_class_init (klass);
+ p++;
+ break;
+ case '[':
+ rank = 1;
+ p++;
+ while (*p) {
+ if (*p == ']')
+ break;
+ if (*p == ',')
+ rank++;
+ else if (*p != '*') { /* '*' means unknown lower bound */
+ g_free (str);
+ return NULL;
+ }
+ ++p;
+ }
+ if (*p != ']') {
+ g_free (str);
+ return NULL;
+ }
+ p++;
+ klass = mono_array_class_get (klass, rank);
+ mono_class_init (klass);
+ break;
+ default:
+ break;
+ }
+ }
+
+ g_free (str);
+
+ ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
+ mono_error_set_pending_exception (&error);
+
+ return ret;
+}
+
+void
+ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+ mono_image_module_basic_init (moduleb);
+}
+
+guint32
+ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str)
+{
+ return mono_image_insert_string (module, str);
+}
+
+void
+ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
+{
+ MonoDynamicImage *image = moduleb->dynamic_image;
+
+ g_assert (type->type);
+ image->wrappers_type = mono_class_from_mono_type (type->type);
+}
}
if (create) {
+ g_assert(!domain->cleanup_semaphore);
+ domain->cleanup_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
+
tpdomain = g_new0 (ThreadPoolDomain, 1);
tpdomain->domain = domain;
domain_add (tpdomain);
g_assert (tpdomain->domain->threadpool_jobs >= 0);
if (tpdomain->domain->threadpool_jobs == 0 && mono_domain_is_unloading (tpdomain->domain)) {
- gboolean removed = domain_remove (tpdomain);
+ gboolean removed;
+
+ removed = domain_remove(tpdomain);
g_assert (removed);
- if (tpdomain->domain->cleanup_semaphore)
- ReleaseSemaphore (tpdomain->domain->cleanup_semaphore, 1, NULL);
+
+ g_assert(tpdomain->domain->cleanup_semaphore);
+ ReleaseSemaphore (tpdomain->domain->cleanup_semaphore, 1, NULL);
domain_free (tpdomain);
tpdomain = NULL;
}
gboolean
mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
{
- gboolean res = TRUE;
- gint64 end;
- gpointer sem;
+ guint32 res;
+ gint64 now, end;
+ ThreadPoolDomain *tpdomain;
g_assert (domain);
g_assert (timeout >= -1);
#endif
/*
- * There might be some threads out that could be about to execute stuff from the given domain.
- * We avoid that by setting up a semaphore to be pulsed by the thread that reaches zero.
- */
- sem = domain->cleanup_semaphore = CreateSemaphore (NULL, 0, 1, NULL);
+ * There might be some threads out that could be about to execute stuff from the given domain.
+ * We avoid that by waiting on a semaphore to be pulsed by the thread that reaches zero.
+ * The semaphore is only created for domains which queued threadpool jobs.
+ * We always wait on the semaphore rather than ensuring domain->threadpool_jobs is 0.
+ * There may be pending outstanding requests which will create new jobs.
+ * The semaphore is signaled the threadpool domain has been removed from list
+ * and we know no more jobs for the domain will be processed.
+ */
+
+ mono_lazy_initialize(&status, initialize);
+ mono_coop_mutex_lock(&threadpool->domains_lock);
+
+ tpdomain = domain_get(domain, FALSE);
+ if (!tpdomain || tpdomain->outstanding_request == 0) {
+ mono_coop_mutex_unlock(&threadpool->domains_lock);
+ return TRUE;
+ }
+ g_assert(domain->cleanup_semaphore);
- /*
- * The memory barrier here is required to have global ordering between assigning to cleanup_semaphone
- * and reading threadpool_jobs. Otherwise this thread could read a stale version of threadpool_jobs
- * and wait forever.
- */
- mono_memory_write_barrier ();
-
- while (domain->threadpool_jobs) {
- gint64 now;
-
- if (timeout != -1) {
- now = mono_msec_ticks ();
- if (now > end) {
- res = FALSE;
- break;
- }
+ if (timeout != -1) {
+ now = mono_msec_ticks();
+ if (now > end) {
+ mono_coop_mutex_unlock(&threadpool->domains_lock);
+ return FALSE;
}
-
- MONO_ENTER_GC_SAFE;
- WaitForSingleObject (sem, timeout != -1 ? end - now : timeout);
- MONO_EXIT_GC_SAFE;
}
+ MONO_ENTER_GC_SAFE;
+ res = WaitForSingleObjectEx(domain->cleanup_semaphore, timeout != -1 ? end - now : timeout, FALSE);
+ MONO_EXIT_GC_SAFE;
+
+ CloseHandle(domain->cleanup_semaphore);
domain->cleanup_semaphore = NULL;
- CloseHandle (sem);
- return res;
+ mono_coop_mutex_unlock(&threadpool->domains_lock);
+
+ return res == WAIT_OBJECT_0;
}
void
HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error);
MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount);
HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error);
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, MonoBoolean *created);
+HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle);
gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle);
void ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle);
MONO_API void
mono_threads_detach_coop (gpointer cookie, gpointer *dummy);
+void mono_threads_begin_abort_protected_block (void);
+void mono_threads_end_abort_protected_block (void);
+MonoException* mono_thread_try_resume_interruption (void);
+
#endif /* _MONO_METADATA_THREADS_TYPES_H_ */
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-error-internals.h>
+#include <mono/utils/w32handle.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/reflection-internals.h>
#define LOCK_THREAD(thread) lock_thread((thread))
#define UNLOCK_THREAD(thread) unlock_thread((thread))
-typedef struct
-{
- guint32 (*func)(void *);
- MonoThread *obj;
- MonoObject *delegate;
- void *start_arg;
-} StartInfo;
-
typedef union {
gint32 ival;
gfloat fval;
/*
* Threads which are starting up and they are not in the 'threads' hash yet.
- * When handle_store is called for a thread, it will be removed from this hash table.
+ * When mono_thread_attach_internal is called for a thread, it will be removed from this hash table.
* Protected by mono_threads_lock ().
*/
static MonoGHashTable *threads_starting_up = NULL;
static guint32 default_stacksize = 0;
#define default_stacksize_for_thread(thread) ((thread)->stack_size? (thread)->stack_size: default_stacksize)
-static void thread_adjust_static_data (MonoInternalThread *thread);
static void context_adjust_static_data (MonoAppContext *ctx);
static void mono_free_static_data (gpointer* static_data);
static void mono_init_static_data_info (StaticDataInfo *static_data);
return MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid);
}
-/* handle_store() and handle_remove() manage the array of threads that
- * still need to be waited for when the main thread exits.
- *
- * If handle_store() returns FALSE the thread must not be started
- * because Mono is shutting down.
- */
-static gboolean handle_store(MonoThread *thread, gboolean force_attach)
-{
- mono_threads_lock ();
-
- THREAD_DEBUG (g_message ("%s: thread %p ID %"G_GSIZE_FORMAT, __func__, thread, (gsize)thread->internal_thread->tid));
-
- if (threads_starting_up)
- mono_g_hash_table_remove (threads_starting_up, thread);
-
- if (shutting_down && !force_attach) {
- mono_threads_unlock ();
- return FALSE;
- }
-
- if(threads==NULL) {
- MONO_GC_REGISTER_ROOT_FIXED (threads, MONO_ROOT_SOURCE_THREADING, "threads table");
- threads=mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREADING, "threads table");
- }
-
- /* We don't need to duplicate thread->handle, because it is
- * only closed when the thread object is finalized by the GC.
- */
- g_assert (thread->internal_thread);
- mono_g_hash_table_insert(threads, (gpointer)(gsize)(thread->internal_thread->tid),
- thread->internal_thread);
-
- mono_threads_unlock ();
-
- return TRUE;
-}
-
-static gboolean handle_remove(MonoInternalThread *thread)
-{
- gboolean ret;
- gsize tid = thread->tid;
-
- THREAD_DEBUG (g_message ("%s: thread ID %"G_GSIZE_FORMAT, __func__, tid));
-
- mono_threads_lock ();
-
- if (threads) {
- /* We have to check whether the thread object for the
- * tid is still the same in the table because the
- * thread might have been destroyed and the tid reused
- * in the meantime, in which case the tid would be in
- * the table, but with another thread object.
- */
- if (mono_g_hash_table_lookup (threads, (gpointer)tid) == thread) {
- mono_g_hash_table_remove (threads, (gpointer)tid);
- ret = TRUE;
- } else {
- ret = FALSE;
- }
- }
- else
- ret = FALSE;
-
- mono_threads_unlock ();
-
- /* Don't close the handle here, wait for the object finalizer
- * to do it. Otherwise, the following race condition applies:
- *
- * 1) Thread exits (and handle_remove() closes the handle)
- *
- * 2) Some other handle is reassigned the same slot
- *
- * 3) Another thread tries to join the first thread, and
- * blocks waiting for the reassigned handle to be signalled
- * (which might never happen). This is possible, because the
- * thread calling Join() still has a reference to the first
- * thread's object.
- */
- return ret;
-}
-
static void ensure_synch_cs_set (MonoInternalThread *thread)
{
MonoCoopMutex *synch_cs;
*/
static void thread_cleanup (MonoInternalThread *thread)
{
+ gboolean ret;
+
g_assert (thread != NULL);
if (thread->abort_state_handle) {
if (InterlockedExchange (&thread->interruption_requested, 0))
InterlockedDecrement (&thread_interruption_requested);
+ mono_threads_lock ();
+
+ if (!threads) {
+ ret = FALSE;
+ } else if (mono_g_hash_table_lookup (threads, (gpointer)thread->tid) != thread) {
+ /* We have to check whether the thread object for the
+ * tid is still the same in the table because the
+ * thread might have been destroyed and the tid reused
+ * in the meantime, in which case the tid would be in
+ * the table, but with another thread object.
+ */
+ ret = FALSE;
+ } else {
+ mono_g_hash_table_remove (threads, (gpointer)thread->tid);
+ ret = TRUE;
+ }
+
+ mono_threads_unlock ();
+
+ /* Don't close the handle here, wait for the object finalizer
+ * to do it. Otherwise, the following race condition applies:
+ *
+ * 1) Thread exits (and thread_cleanup() closes the handle)
+ *
+ * 2) Some other handle is reassigned the same slot
+ *
+ * 3) Another thread tries to join the first thread, and
+ * blocks waiting for the reassigned handle to be signalled
+ * (which might never happen). This is possible, because the
+ * thread calling Join() still has a reference to the first
+ * thread's object.
+ */
+
/* if the thread is not in the hash it has been removed already */
- if (!handle_remove (thread)) {
+ if (!ret) {
if (thread == mono_thread_internal_current ()) {
mono_domain_unset ();
mono_memory_barrier ();
}
- /* This needs to be called even if handle_remove () fails */
if (mono_thread_cleanup_fn)
mono_thread_cleanup_fn (thread_get_tid (thread));
return;
return thread;
}
+static void
+mono_alloc_static_data (gpointer **static_data_ptr, guint32 offset, gboolean threadlocal);
+
static gboolean
-init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
+mono_thread_attach_internal (MonoThread *thread, gboolean force_attach, gboolean force_domain, gsize *stack_ptr)
{
- MonoDomain *domain = mono_get_root_domain ();
+ MonoThreadInfo *info;
+ MonoInternalThread *internal;
+ MonoDomain *domain, *root_domain;
+
+ g_assert (thread);
+
+ info = mono_thread_info_current ();
+
+ internal = thread->internal_thread;
+ internal->handle = mono_thread_info_get_handle (info);
+ internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ());
+ internal->thread_info = info;
+ internal->small_id = info->small_id;
+ internal->stack_ptr = stack_ptr;
+
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
+
+ SET_CURRENT_OBJECT (internal);
- if (!candidate || candidate->obj.vtable->domain != domain) {
- candidate = new_thread_with_internal (domain, thread);
+ domain = mono_object_domain (thread);
+
+ mono_thread_push_appdomain_ref (domain);
+ if (!mono_domain_set (domain, force_domain)) {
+ mono_thread_pop_appdomain_ref ();
+ return FALSE;
+ }
+
+ mono_threads_lock ();
+
+ if (threads_starting_up)
+ mono_g_hash_table_remove (threads_starting_up, thread);
+
+ if (shutting_down && !force_attach) {
+ mono_threads_unlock ();
+ return FALSE;
+ }
+
+ if (!threads) {
+ MONO_GC_REGISTER_ROOT_FIXED (threads, MONO_ROOT_SOURCE_THREADING, "threads table");
+ threads = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREADING, "threads table");
+ }
+
+ /* We don't need to duplicate thread->handle, because it is
+ * only closed when the thread object is finalized by the GC. */
+ mono_g_hash_table_insert (threads, (gpointer)(gsize)(internal->tid), internal);
+
+ /* We have to do this here because mono_thread_start_cb
+ * requires that root_domain_thread is set up. */
+ if (thread_static_info.offset || thread_static_info.idx > 0) {
+ /* get the current allocated size */
+ guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (thread_static_info.idx, thread_static_info.offset, 0);
+ mono_alloc_static_data (&internal->static_data, offset, TRUE);
}
- set_current_thread_for_domain (domain, thread, candidate);
- g_assert (!thread->root_domain_thread);
- MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
+
+ mono_threads_unlock ();
+
+ root_domain = mono_get_root_domain ();
+
+ g_assert (!internal->root_domain_thread);
+ if (domain != root_domain)
+ MONO_OBJECT_SETREF (internal, root_domain_thread, new_thread_with_internal (root_domain, internal));
+ else
+ MONO_OBJECT_SETREF (internal, root_domain_thread, thread);
+
+ if (domain != root_domain)
+ set_current_thread_for_domain (root_domain, internal, internal->root_domain_thread);
+
+ set_current_thread_for_domain (domain, internal, thread);
+
+ THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, internal->tid, internal->handle));
+
return TRUE;
}
-static guint32 WINAPI start_wrapper_internal(void *data)
+typedef struct {
+ gint32 ref;
+ MonoThread *thread;
+ MonoObject *start_delegate;
+ MonoObject *start_delegate_arg;
+ MonoThreadStart start_func;
+ gpointer start_func_arg;
+ gboolean failed;
+ MonoCoopSem registered;
+} StartInfo;
+
+static guint32 WINAPI start_wrapper_internal(StartInfo *start_info, gsize *stack_ptr)
{
MonoError error;
- MonoThreadInfo *info;
- StartInfo *start_info = (StartInfo *)data;
- guint32 (*start_func)(void *);
- void *start_arg;
+ MonoThreadStart start_func;
+ void *start_func_arg;
gsize tid;
/*
- * We don't create a local to hold start_info->obj, so hopefully it won't get pinned during a
+ * We don't create a local to hold start_info->thread, so hopefully it won't get pinned during a
* GC stack walk.
*/
- MonoInternalThread *internal = start_info->obj->internal_thread;
- MonoObject *start_delegate = start_info->delegate;
- MonoDomain *domain = start_info->obj->obj.vtable->domain;
+ MonoThread *thread;
+ MonoInternalThread *internal;
+ MonoObject *start_delegate;
+ MonoObject *start_delegate_arg;
+ MonoDomain *domain;
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, mono_native_thread_id_get ()));
+ thread = start_info->thread;
+ internal = thread->internal_thread;
+ domain = mono_object_domain (start_info->thread);
- /* We can be sure start_info->obj->tid and
- * start_info->obj->handle have been set, because the thread
- * was created suspended, and these values were set before the
- * thread resumed
- */
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, mono_native_thread_id_get ()));
- info = mono_thread_info_current ();
- g_assert (info);
- internal->thread_info = info;
- internal->small_id = info->small_id;
+ if (!mono_thread_attach_internal (thread, FALSE, FALSE, stack_ptr)) {
+ start_info->failed = TRUE;
- tid = internal->tid;
+ mono_coop_sem_post (&start_info->registered);
- SET_CURRENT_OBJECT (internal);
+ if (InterlockedDecrement (&start_info->ref) == 0) {
+ mono_coop_sem_destroy (&start_info->registered);
+ g_free (start_info);
+ }
- /* Every thread references the appdomain which created it */
- mono_thread_push_appdomain_ref (domain);
-
- if (!mono_domain_set (domain, FALSE)) {
- /* No point in raising an appdomain_unloaded exception here */
- /* FIXME: Cleanup here */
- mono_thread_pop_appdomain_ref ();
return 0;
}
- start_func = start_info->func;
- start_arg = start_info->obj->start_obj;
- if (!start_arg)
- start_arg = start_info->start_arg;
+ tid = internal->tid;
- /* We have to do this here because mono_thread_new_init()
- requires that root_domain_thread is set up. */
- thread_adjust_static_data (internal);
- init_root_domain_thread (internal, start_info->obj);
+ start_delegate = start_info->start_delegate;
+ start_delegate_arg = start_info->start_delegate_arg;
+ start_func = start_info->start_func;
+ start_func_arg = start_info->start_func_arg;
/* This MUST be called before any managed code can be
* executed, as it calls the callback function that (for the
* jit) sets the lmf marker.
*/
- mono_thread_new_init (tid, &tid, start_func);
- internal->stack_ptr = &tid;
- if (domain != mono_get_root_domain ())
- set_current_thread_for_domain (domain, internal, start_info->obj);
- LIBGC_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", __func__, mono_native_thread_id_get (), getpid (), thread->stack_ptr));
-
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
+ if (mono_thread_start_cb)
+ mono_thread_start_cb (tid, stack_ptr, start_func);
/* On 2.0 profile (and higher), set explicitly since state might have been
Unknown */
mono_thread_init_apartment_state ();
- if(internal->start_notify!=NULL) {
- /* Let the thread that called Start() know we're
- * ready
- */
- ReleaseSemaphore (internal->start_notify, 1, NULL);
+ /* Let the thread that called Start() know we're ready */
+ mono_coop_sem_post (&start_info->registered);
+
+ if (InterlockedDecrement (&start_info->ref) == 0) {
+ mono_coop_sem_destroy (&start_info->registered);
+ g_free (start_info);
}
- g_free (start_info);
- THREAD_DEBUG (g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
- internal->tid));
+ /* start_info is not valid anymore */
+ start_info = NULL;
/*
* Call this after calling start_notify, since the profiler callback might want
/* start_func is set only for unmanaged start functions */
if (start_func) {
- start_func (start_arg);
+ start_func (start_func_arg);
} else {
void *args [1];
+
g_assert (start_delegate != NULL);
- args [0] = start_arg;
+
/* we may want to handle the exception here. See comment below on unhandled exceptions */
+ args [0] = (gpointer) start_delegate_arg;
mono_runtime_delegate_invoke_checked (start_delegate, args, &error);
if (!mono_error_ok (&error)) {
static gsize WINAPI start_wrapper(void *data)
{
- volatile int dummy;
+ volatile gsize dummy;
/* Avoid scanning the frames above this frame during a GC */
mono_gc_set_stack_end ((void*)&dummy);
- return start_wrapper_internal (data);
+ return start_wrapper_internal ((StartInfo*) data, (gsize*) &dummy);
}
/*
* LOCKING: Acquires the threads lock.
*/
static gboolean
-create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *start_info, gboolean threadpool_thread, guint32 stack_size,
- MonoError *error)
+create_thread (MonoThread *thread, MonoInternalThread *internal, MonoObject *start_delegate, MonoThreadStart start_func, gpointer start_func_arg,
+ gboolean threadpool_thread, guint32 stack_size, MonoError *error)
{
+ StartInfo *start_info = NULL;
HANDLE thread_handle;
MonoNativeThreadId tid;
MonoThreadParm tp;
+ gboolean ret;
+
+ if (start_delegate)
+ g_assert (!start_func && !start_func_arg);
+ if (start_func)
+ g_assert (!start_delegate);
/*
* Join joinable threads to prevent running out of threads since the finalizer
mono_threads_lock ();
if (shutting_down) {
- g_free (start_info);
mono_threads_unlock ();
return FALSE;
}
mono_g_hash_table_insert (threads_starting_up, thread, thread);
mono_threads_unlock ();
- internal->start_notify = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
- if (!internal->start_notify) {
- mono_threads_lock ();
- mono_g_hash_table_remove (threads_starting_up, thread);
- mono_threads_unlock ();
- g_warning ("%s: CreateSemaphore error 0x%x", __func__, GetLastError ());
- g_free (start_info);
- return FALSE;
- }
+ internal->threadpool_thread = threadpool_thread;
+ if (threadpool_thread)
+ mono_thread_set_state (internal, ThreadState_Background);
+
+ start_info = g_new0 (StartInfo, 1);
+ start_info->ref = 2;
+ start_info->thread = thread;
+ start_info->start_delegate = start_delegate;
+ start_info->start_delegate_arg = thread->start_obj;
+ start_info->start_func = start_func;
+ start_info->start_func_arg = start_func_arg;
+ start_info->failed = FALSE;
+ mono_coop_sem_init (&start_info->registered, 0);
if (stack_size == 0)
stack_size = default_stacksize_for_thread (internal);
- /* Create suspended, so we can do some housekeeping before the thread
- * starts
- */
tp.priority = thread->priority;
tp.stack_size = stack_size;
- tp.creation_flags = CREATE_SUSPENDED;
+ tp.creation_flags = 0;
thread_handle = mono_threads_create_thread (start_wrapper, start_info, &tp, &tid);
mono_threads_lock ();
mono_g_hash_table_remove (threads_starting_up, thread);
mono_threads_unlock ();
- g_free (start_info);
mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", GetLastError());
- return FALSE;
+ /* ref is not going to be decremented in start_wrapper_internal */
+ InterlockedDecrement (&start_info->ref);
+ ret = FALSE;
+ goto done;
}
- THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
-
- internal->handle = thread_handle;
- internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
-
- internal->threadpool_thread = threadpool_thread;
- if (threadpool_thread)
- mono_thread_set_state (internal, ThreadState_Background);
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
- /* Only store the handle when the thread is about to be
- * launched, to avoid the main thread deadlocking while trying
- * to clean up a thread that will never be signalled.
+ /*
+ * Wait for the thread to set up its TLS data etc, so
+ * theres no potential race condition if someone tries
+ * to look up the data believing the thread has
+ * started
*/
- if (!handle_store (thread, FALSE))
- return FALSE;
- mono_thread_info_resume (tid);
+ mono_coop_sem_wait (&start_info->registered, MONO_SEM_FLAGS_NONE);
- if (internal->start_notify) {
- /*
- * Wait for the thread to set up its TLS data etc, so
- * theres no potential race condition if someone tries
- * to look up the data believing the thread has
- * started
- */
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
- MONO_ENTER_GC_SAFE;
- WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
- MONO_EXIT_GC_SAFE;
+ ret = !start_info->failed;
- CloseHandle (internal->start_notify);
- internal->start_notify = NULL;
+done:
+ if (InterlockedDecrement (&start_info->ref) == 0) {
+ mono_coop_sem_destroy (&start_info->registered);
+ g_free (start_info);
}
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
-
- return TRUE;
+ return ret;
}
void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
{
MonoThread *thread;
MonoInternalThread *internal;
- StartInfo *start_info;
gboolean res;
mono_error_init (error);
MONO_OBJECT_SETREF (thread, internal_thread, internal);
- start_info = g_new0 (StartInfo, 1);
- start_info->func = (guint32 (*)(void *))func;
- start_info->obj = thread;
- start_info->start_arg = arg;
-
- res = create_thread (thread, internal, start_info, threadpool_thread, stack_size, error);
+ res = create_thread (thread, internal, NULL, (MonoThreadStart) func, arg, threadpool_thread, stack_size, error);
return_val_if_nok (error, NULL);
/* Check that the managed and unmanaged layout of MonoInternalThread matches */
MonoThread *
mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
{
- MonoThreadInfo *info;
- MonoInternalThread *thread;
- MonoThread *current_thread;
- HANDLE thread_handle;
+ MonoInternalThread *internal;
+ MonoThread *thread;
MonoNativeThreadId tid;
+ gsize stack_ptr;
- if ((thread = mono_thread_internal_current ())) {
+ if ((internal = mono_thread_internal_current ())) {
if (domain != mono_domain_get ())
mono_domain_set (domain, TRUE);
/* Already attached */
g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", mono_native_thread_id_get ());
}
- thread = create_internal_thread ();
-
- thread_handle = mono_thread_info_open_handle ();
- g_assert (thread_handle);
-
tid=mono_native_thread_id_get ();
- thread->handle = thread_handle;
- thread->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
- thread->stack_ptr = &tid;
-
- THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
-
- info = mono_thread_info_current ();
- g_assert (info);
- thread->thread_info = info;
- thread->small_id = info->small_id;
+ internal = create_internal_thread ();
- current_thread = new_thread_with_internal (domain, thread);
+ thread = new_thread_with_internal (domain, internal);
- if (!handle_store (current_thread, force_attach)) {
+ if (!mono_thread_attach_internal (thread, force_attach, TRUE, &stack_ptr)) {
/* Mono is shutting down, so just wait for the end */
for (;;)
mono_thread_info_sleep (10000, NULL);
}
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), thread));
-
- SET_CURRENT_OBJECT (thread);
- mono_domain_set (domain, TRUE);
-
- thread_adjust_static_data (thread);
-
- init_root_domain_thread (thread, current_thread);
-
- if (domain != mono_get_root_domain ())
- set_current_thread_for_domain (domain, thread, current_thread);
-
+ THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, internal->handle));
if (mono_thread_attach_cb) {
guint8 *staddr;
mono_thread_info_get_stack_bounds (&staddr, &stsize);
if (staddr == NULL)
- mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), &tid);
+ mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), &stack_ptr);
else
mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), staddr + stsize);
}
/* Can happen when we attach the profiler helper thread in order to heapshot. */
- if (!info->tools_thread)
+ if (!mono_thread_info_current ()->tools_thread)
// FIXME: Need a separate callback
mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
- return current_thread;
+ return thread;
}
void
SET_CURRENT_OBJECT (NULL);
mono_domain_unset ();
- /* Don't need to CloseHandle this thread, even though we took a
+ /* Don't need to close the handle to this thread, even though we took a
* reference in mono_thread_attach (), because the GC will do it
* when the Thread object is finalised.
*/
MonoObject *start)
{
MonoError error;
- StartInfo *start_info;
MonoInternalThread *internal;
gboolean res;
UNLOCK_THREAD (internal);
return this_obj;
}
- /* This is freed in start_wrapper */
- start_info = g_new0 (StartInfo, 1);
- start_info->func = NULL;
- start_info->start_arg = NULL;
- start_info->delegate = start;
- start_info->obj = this_obj;
- g_assert (this_obj->obj.vtable->domain == mono_domain_get ());
- res = create_thread (this_obj, internal, start_info, FALSE, 0, &error);
+ res = create_thread (this_obj, internal, start, NULL, NULL, FALSE, 0, &error);
if (!res) {
mono_error_cleanup (&error);
UNLOCK_THREAD (internal);
* when thread_cleanup () can be called after this.
*/
if (thread)
- CloseHandle (thread);
+ mono_threads_close_thread_handle (thread);
if (this_obj->synch_cs) {
MonoCoopMutex *synch_cs = this_obj->synch_cs;
gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms)
{
MonoError error;
- HANDLE handles [MAXIMUM_WAIT_OBJECTS];
+ HANDLE handles [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
uintptr_t numhandles;
guint32 ret;
guint32 i;
return map_native_wait_result_to_managed (WAIT_FAILED);
numhandles = mono_array_length(mono_handles);
- if (numhandles > MAXIMUM_WAIT_OBJECTS)
+ if (numhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS)
return map_native_wait_result_to_managed (WAIT_FAILED);
for(i = 0; i < numhandles; i++) {
}
*error = GetLastError ();
+
return(sem);
}
HANDLE sem;
sem = OpenSemaphore (rights, FALSE, mono_string_chars (name));
+
*error = GetLastError ();
return(sem);
}
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, MonoBoolean *created)
+HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
{
HANDLE event;
-
- *created = TRUE;
if (name == NULL) {
event = CreateEvent (NULL, manual, initial, NULL);
} else {
event = CreateEvent (NULL, manual, initial,
mono_string_chars (name));
-
- if (GetLastError () == ERROR_ALREADY_EXISTS) {
- *created = FALSE;
- }
}
-
+
+ *error = GetLastError ();
+
return(event);
}
{
HANDLE ret;
- *error = ERROR_SUCCESS;
-
ret = OpenEvent (rights, FALSE, mono_string_chars (name));
if (ret == NULL) {
*error = GetLastError ();
+ } else {
+ *error = ERROR_SUCCESS;
}
-
+
return(ret);
}
struct wait_data
{
- HANDLE handles[MAXIMUM_WAIT_OBJECTS];
- MonoInternalThread *threads[MAXIMUM_WAIT_OBJECTS];
+ HANDLE handles[MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
+ MonoInternalThread *threads[MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
guint32 num;
};
-static void wait_for_tids (struct wait_data *wait, guint32 timeout)
+static void
+wait_for_tids (struct wait_data *wait, guint32 timeout)
{
guint32 i, ret;
}
for(i=0; i<wait->num; i++)
- CloseHandle (wait->handles[i]);
+ mono_threads_close_thread_handle (wait->handles [i]);
if (ret == WAIT_TIMEOUT)
return;
* to background mode.
*/
count = wait->num;
- if (count < MAXIMUM_WAIT_OBJECTS) {
+ if (count < MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
wait->handles [count] = background_change_event;
count++;
}
}
for(i=0; i<wait->num; i++)
- CloseHandle (wait->handles[i]);
+ mono_threads_close_thread_handle (wait->handles [i]);
if (ret == WAIT_TIMEOUT)
return;
{
struct wait_data *wait=(struct wait_data *)user;
- if(wait->num<MAXIMUM_WAIT_OBJECTS) {
+ if(wait->num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
HANDLE handle;
MonoInternalThread *thread=(MonoInternalThread *)value;
MonoInternalThread *thread = (MonoInternalThread *)value;
HANDLE handle;
- if (wait->num >= MAXIMUM_WAIT_OBJECTS)
+ if (wait->num >= MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS)
return FALSE;
/* The finalizer thread is not a background thread */
ResetEvent (background_change_event);
wait->num=0;
/*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
- memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
+ memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
mono_g_hash_table_foreach (threads, build_wait_tids, wait);
mono_threads_unlock ();
if(wait->num>0) {
wait->num = 0;
/*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
- memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
+ memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
mono_g_hash_table_foreach_remove (threads, remove_and_abort_threads, wait);
mono_threads_unlock ();
HANDLE handle;
/*
- * We try to exclude threads early, to avoid running into the MAXIMUM_WAIT_OBJECTS
+ * We try to exclude threads early, to avoid running into the MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS
* limitation.
* This needs no locking.
*/
(thread->state & ThreadState_Stopped) != 0)
return;
- if (wait->num<MAXIMUM_WAIT_OBJECTS) {
+ if (wait->num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
if (handle == NULL)
return;
/*
* We make multiple calls to WaitForMultipleObjects since:
- * - we can only wait for MAXIMUM_WAIT_OBJECTS threads
+ * - we can only wait for MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS threads
* - some threads could exit without becoming suspended
*/
finished = FALSE;
*/
wait->num = 0;
/*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
- memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
+ memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
mono_threads_lock ();
mono_g_hash_table_foreach (threads, collect_threads_for_suspend, wait);
mono_threads_unlock ();
|| mono_gc_is_finalizer_internal_thread (thread)
|| (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)
) {
- //CloseHandle (wait->handles [i]);
+ //mono_threads_close_thread_handle (wait->handles [i]);
wait->threads [i] = NULL; /* ignore this thread in next loop */
continue;
}
(thread->state & ThreadState_StopRequested) != 0 ||
(thread->state & ThreadState_Stopped) != 0) {
UNLOCK_THREAD (thread);
- CloseHandle (wait->handles [i]);
+ mono_threads_close_thread_handle (wait->handles [i]);
wait->threads [i] = NULL; /* ignore this thread in next loop */
continue;
}
if (mono_thread_internal_has_appdomain_ref (thread, domain)) {
/* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */
- if(data->wait.num<MAXIMUM_WAIT_OBJECTS) {
+ if(data->wait.num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
HANDLE handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
if (handle == NULL)
return;
return offset;
}
-/*
- * ensure thread static fields already allocated are valid for thread
- * This function is called when a thread is created or on thread attach.
- */
-static void
-thread_adjust_static_data (MonoInternalThread *thread)
-{
- mono_threads_lock ();
- if (thread_static_info.offset || thread_static_info.idx > 0) {
- /* get the current allocated size */
- guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (thread_static_info.idx, thread_static_info.offset, 0);
- mono_alloc_static_data (&thread->static_data, offset, TRUE);
- }
- mono_threads_unlock ();
-}
-
/*
* LOCKING: requires that threads_mutex is held
*/
thread->state & ThreadState_Background)
ExitThread (1);
#endif
-
if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
return NULL;
InterlockedIncrement (&thread_interruption_requested);
if (mono_get_eh_callbacks ()->mono_install_handler_block_guard (mono_thread_info_get_suspend_state (info)))
return MonoResumeThread;
+ /*
+ The target thread is running at least one protected block, which must not be interrupted, so we give up.
+ The protected block code will give them a chance when appropriate.
+ */
+ if (thread->abort_protected_block_count)
+ return MonoResumeThread;
+
/*someone is already interrupting it*/
if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
return MonoResumeThread;
/* FIXME this is insanely broken, it doesn't cause interruption to happen synchronously
* since passing FALSE to mono_thread_request_interruption makes sure it returns NULL */
+ /*
+ Self aborts ignore the protected block logic and raise the TAE regardless. This is verified by one of the tests in mono/tests/abort-cctor.cs.
+ */
exc = mono_thread_request_interruption (TRUE);
if (exc)
mono_error_set_exception_instance (error, exc);
void
mono_thread_internal_unhandled_exception (MonoObject* exc)
{
- if (mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT) {
- MonoClass *klass = exc->vtable->klass;
- if (is_threadabort_exception (klass)) {
- mono_thread_internal_reset_abort (mono_thread_internal_current ());
- } else if (!is_appdomainunloaded_exception (klass)) {
- mono_unhandled_exception (exc);
- if (mono_environment_exitcode_get () == 1) {
- mono_environment_exitcode_set (255);
- mono_invoke_unhandled_exception_hook (exc);
- g_assert_not_reached ();
- }
+ MonoClass *klass = exc->vtable->klass;
+ if (is_threadabort_exception (klass)) {
+ mono_thread_internal_reset_abort (mono_thread_internal_current ());
+ } else if (!is_appdomainunloaded_exception (klass)
+ && mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT) {
+ mono_unhandled_exception (exc);
+ if (mono_environment_exitcode_get () == 1) {
+ mono_environment_exitcode_set (255);
+ mono_invoke_unhandled_exception_hook (exc);
+ g_assert_not_reached ();
}
}
}
}
}
}
+
+void
+mono_threads_begin_abort_protected_block (void)
+{
+ MonoInternalThread *thread;
+
+ thread = mono_thread_internal_current ();
+ ++thread->abort_protected_block_count;
+ mono_memory_barrier ();
+}
+
+void
+mono_threads_end_abort_protected_block (void)
+{
+ MonoInternalThread *thread;
+
+ thread = mono_thread_internal_current ();
+
+ mono_memory_barrier ();
+ --thread->abort_protected_block_count;
+}
+
+MonoException*
+mono_thread_try_resume_interruption (void)
+{
+ MonoInternalThread *thread;
+
+ thread = mono_thread_internal_current ();
+ if (thread->abort_protected_block_count || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ())
+ return NULL;
+
+ return mono_thread_resume_interruption ();
+}
\ No newline at end of file
#include <config.h>
#include <mono/metadata/object-internals.h>
+#include <mono/metadata/dynamic-image-internals.h>
#include <mono/metadata/verify.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/opcodes.h>
token_bounds_check (MonoImage *image, guint32 token)
{
if (image_is_dynamic (image))
- return mono_reflection_is_valid_dynamic_token ((MonoDynamicImage*)image, token);
+ return mono_dynamic_image_is_valid_token ((MonoDynamicImage*)image, token);
return image->tables [mono_metadata_token_table (token)].rows >= mono_metadata_token_index (token) && mono_metadata_token_index (token) > 0;
}
/mono-boehm
/buildver-sgen.h
/buildver-boehm.h
-/regressionexitcode.out
+/regressiontests.out
mini-darwin.c
windows_sources = \
- mini-windows.c
+ mini-windows.c \
+ mini-windows-dllmain.c
posix_sources = \
mini-posix.c
for i in $(regtests); do $(MINI_RUNTIME) $$i; done
rcheck-nunit: mono $(regtests)
- -($(MINI_RUNTIME) --regression $(regtests); echo $$? > regressionexitcode.out) | $(srcdir)/emitnunit.pl
- exit $$(cat regressionexitcode.out)
+ $(MINI_RUNTIME) --regression $(regtests) > regressiontests.out 2>&1; cat regressiontests.out; \
+ if grep -q "100% pass" regressiontests.out; then successbool=True; failurescount=0; else successbool=False; failurescount=1; fi; \
+ echo "<?xml version='1.0' encoding='utf-8'?>\
+ <test-results failures='$$failurescount' total='1' not-run='0' name='regression-tests.dummy' date='$$(date +%F)' time='$$(date +%T)'>\
+ <test-suite name='regression-tests.dummy' success='$$successbool' time='0'>\
+ <results><test-case name='MonoTests.regressions.100percentsuccess' executed='True' success='$$successbool' time='0'>" > TestResult-regression.xml; \
+ if [ "$$successbool" = "False" ]; then echo "<failure><message><![CDATA[$$(cat regressiontests.out)]]></message><stack-trace></stack-trace></failure>" >> TestResult-regression.xml; fi; \
+ echo "</test-case></results>\
+ </test-suite>\
+ </test-results>" >> TestResult-regression.xml; exit $$failurescount
rcheck: mono $(regtests)
$(MINI_RUNTIME) --regression $(regtests)
EXTRA_DIST = TestDriver.cs \
TestHelpers.cs \
genmdesc.pl \
- emitnunit.pl \
$(test_sources) \
$(x86_sources) cpu-x86.md \
$(amd64_sources) cpu-amd64.md \
case OP_LOADU4_MEMBASE:
case OP_LOADI1_MEMBASE:
case OP_LOADI8_MEMBASE:
+#ifndef MONO_ARCH_SOFT_FLOAT_FALLBACK
case OP_LOADR4_MEMBASE:
+#endif
case OP_LOADR8_MEMBASE:
if (ins->inst_offset != 0)
continue;
case OP_STOREI2_MEMBASE_REG:
case OP_STOREI4_MEMBASE_REG:
case OP_STOREI8_MEMBASE_REG:
+#ifndef MONO_ARCH_SOFT_FLOAT_FALLBACK
case OP_STORER4_MEMBASE_REG:
+#endif
case OP_STORER8_MEMBASE_REG:
case OP_STOREV_MEMBASE:
if (ins->inst_offset != 0)
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
#else
// Default (linux)
- char *args = g_strdup_printf ("%s %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
+ char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
return 1;
+#endif
+#ifndef ENABLE_LLVM
+ aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with llvm support.\n");
+ return 1;
#endif
}
}
}
- if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY))) {
+ if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) ||
+ (mono_llvm_only && method && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
res = init_method (amodule, method_index, method, NULL, NULL, error);
if (!res)
goto cleanup;
atomic_cas_i4: dest:i src1:i src2:i src3:i len:32
atomic_cas_i8: dest:i src1:i src2:i src3:i len:32
memory_barrier: len:8 clob:a
-atomic_load_i1: dest:i src1:b len:20
-atomic_load_u1: dest:i src1:b len:20
-atomic_load_i2: dest:i src1:b len:20
-atomic_load_u2: dest:i src1:b len:20
-atomic_load_i4: dest:i src1:b len:16
-atomic_load_u4: dest:i src1:b len:16
-atomic_load_i8: dest:i src1:b len:12
-atomic_load_u8: dest:i src1:b len:12
-atomic_load_r4: dest:f src1:b len:24
-atomic_load_r8: dest:f src1:b len:20
-atomic_store_i1: dest:b src1:i len:16
-atomic_store_u1: dest:b src1:i len:16
-atomic_store_i2: dest:b src1:i len:16
-atomic_store_u2: dest:b src1:i len:16
-atomic_store_i4: dest:b src1:i len:16
-atomic_store_u4: dest:b src1:i len:16
-atomic_store_i8: dest:b src1:i len:12
-atomic_store_u8: dest:b src1:i len:12
-atomic_store_r4: dest:b src1:f len:24
-atomic_store_r8: dest:b src1:f len:20
+atomic_load_i1: dest:i src1:b len:24
+atomic_load_u1: dest:i src1:b len:24
+atomic_load_i2: dest:i src1:b len:24
+atomic_load_u2: dest:i src1:b len:24
+atomic_load_i4: dest:i src1:b len:24
+atomic_load_u4: dest:i src1:b len:24
+atomic_load_i8: dest:i src1:b len:20
+atomic_load_u8: dest:i src1:b len:20
+atomic_load_r4: dest:f src1:b len:28
+atomic_load_r8: dest:f src1:b len:24
+atomic_store_i1: dest:b src1:i len:20
+atomic_store_u1: dest:b src1:i len:20
+atomic_store_i2: dest:b src1:i len:20
+atomic_store_u2: dest:b src1:i len:20
+atomic_store_i4: dest:b src1:i len:20
+atomic_store_u4: dest:b src1:i len:20
+atomic_store_i8: dest:b src1:i len:20
+atomic_store_u8: dest:b src1:i len:20
+atomic_store_r4: dest:b src1:f len:28
+atomic_store_r8: dest:b src1:f len:24
generic_class_init: src1:a len:44 clob:c
gc_safe_point: src1:i len:12 clob:c
thread->internal_thread->state |= ThreadState_Background;
thread->internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
- mono_set_is_debugger_attached (TRUE);
-
if (agent_config.defer) {
if (!wait_for_attach ()) {
DEBUG_PRINTF (1, "[dbg] Can't attach, aborting debugger thread.\n");
attach_failed = TRUE; // Don't abort process when we can't listen
} else {
+ mono_set_is_debugger_attached (TRUE);
/* Send start event to client */
process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ());
}
+ } else {
+ mono_set_is_debugger_attached (TRUE);
}
while (!attach_failed) {
int op_noimm = mono_op_imm_to_op (ins->opcode);
MonoJitICallInfo *info;
+ /*
+ * These opcodes don't have logical equivalence to the emulating native
+ * function. They are decomposed in specific fashion in mono_decompose_soft_float.
+ */
+ if (MONO_HAS_CUSTOM_EMULATION (ins))
+ continue;
+
/*
* Emulation can't handle _IMM ops. If this is an imm opcode we need
* to check whether its non-imm counterpart is emulated and, if so,
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-hwcap.h"
#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/w32handle.h"
#include "mini.h"
#include "jit.h"
#define error_if_aot_unsupported()
#endif
-#ifdef HOST_WIN32
-BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
-{
- if (!mono_gc_dllmain (module_handle, reason, reserved))
- return FALSE;
-
- switch (reason)
- {
- case DLL_PROCESS_ATTACH:
- mono_install_runtime_load (mini_init);
- break;
- case DLL_PROCESS_DETACH:
- if (coree_module_handle)
- FreeLibrary (coree_module_handle);
- break;
- case DLL_THREAD_DETACH:
- mono_thread_info_detach ();
- break;
-
- }
- return TRUE;
-}
-#endif
-
static gboolean enable_debugging;
/*
mono_counters_init ();
+#ifndef HOST_WIN32
+ mono_w32handle_init ();
+#endif
+
/* Set rootdir before loading config */
mono_set_rootdir ();
+++ /dev/null
-#!/usr/bin/perl
-use strict;
-use warnings;
-use Cwd;
-use POSIX qw(strftime uname locale_h);
-use Net::Domain qw(hostname hostfqdn);
-use locale;
-
-my $line;
-foreach $line (<STDIN>) {
- chomp ($line);
- print "$line\n";
- if ($line =~ /^Overall results:/) {
- # do magic nunit emission here
- # failures look like:
- # Overall results: tests: 19992, failed: 48, opt combinations: 24 (pass: 99.76%)
- # passes look like:
- # Overall results: tests: 20928, 100% pass, opt combinations: 24
- my @words = split (/ /, $line);
- my $failed;
- my $successbool;
- my $total = $words[3];
- my $mylocale = setlocale (LC_CTYPE);
- $mylocale = substr($mylocale, 0, index($mylocale, '.'));
- $mylocale =~ s/_/-/;
- if ($line =~ /failed:/) {
- $failed = $words[5];
- } else {
- $failed = "0,";
- }
- chop ($failed);
- chop ($total);
- if ($failed > 0) {
- $successbool = "False";
- } else {
- $successbool = "True";
- }
- open (my $nunitxml, '>', 'TestResult-regression.xml') or die "Could not write to 'TestResult-regression.xml' $!";
- print $nunitxml "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n";
- print $nunitxml "<!--This file represents the results of running a test suite-->\n";
- print $nunitxml "<test-results name=\"regression-tests.dummy\" total=\"$total\" failures=\"$failed\" not-run=\"0\" date=\"" . strftime ("%F", localtime) . "\" time=\"" . strftime ("%T", localtime) . "\">\n";
- print $nunitxml " <environment nunit-version=\"2.4.8.0\" clr-version=\"4.0.30319.17020\" os-version=\"Unix " . (uname ())[2] . "\" platform=\"Unix\" cwd=\"" . getcwd . "\" machine-name=\"" . hostname . "\" user=\"" . getpwuid ($<) . "\" user-domain=\"" . hostfqdn . "\" />\n";
- print $nunitxml " <culture-info current-culture=\"$mylocale\" current-uiculture=\"$mylocale\" />\n";
- print $nunitxml " <test-suite name=\"regression-tests.dummy\" success=\"$successbool\" time=\"0\" asserts=\"0\">\n";
- print $nunitxml " <results>\n";
- print $nunitxml " <test-suite name=\"MonoTests\" success=\"$successbool\" time=\"0\" asserts=\"0\">\n";
- print $nunitxml " <results>\n";
- print $nunitxml " <test-suite name=\"regressions\" success=\"$successbool\" time=\"0\" asserts=\"0\">\n";
- print $nunitxml " <results>\n";
- print $nunitxml " <test-case name=\"MonoTests.regressions.100percentsuccess\" executed=\"True\" success=\"$successbool\" time=\"0\" asserts=\"0\"";
- if ( $failed > 0) {
- print $nunitxml ">\n";
- print $nunitxml " <failure>\n";
- print $nunitxml " <message><![CDATA[";
- foreach $line (<STDIN>) {
- chomp ($line);
- print "$line\n";
- }
- print $nunitxml "]]></message>\n";
- print $nunitxml " <stack-trace>\n";
- print $nunitxml " </stack-trace>\n";
- print $nunitxml " </failure>\n";
- print $nunitxml " </test-case>\n";
- } else {
- print $nunitxml " />\n";
- }
- print $nunitxml " </results>\n";
- print $nunitxml " </test-suite>\n";
- print $nunitxml " </results>\n";
- print $nunitxml " </test-suite>\n";
- print $nunitxml " </results>\n";
- print $nunitxml " </test-suite>\n";
- print $nunitxml "</test-results>\n";
- close $nunitxml;
- }
-}
g_free (callee_name);
g_free (caller_name);
}
+
+void
+mono_dummy_jit_icall (void)
+{
+}
void mono_throw_method_access (MonoMethod *callee, MonoMethod *caller);
+void mono_dummy_jit_icall (void);
+
#endif /* __MONO_JIT_ICALLS_H__ */
}
case OP_IDIV_UN_IMM:
case OP_IDIV_IMM: {
- allocated_vregs = mono_strength_reduction_division (cfg, ins);
+ if (!COMPILE_LLVM (cfg))
+ allocated_vregs = mono_strength_reduction_division (cfg, ins);
break;
}
#if SIZEOF_REGISTER == 8
#include <config.h>
#include <fcntl.h>
#include <mono/metadata/assembly.h>
+#include <mono/metadata/mono-config.h>
#include <mono/utils/mono-mmap.h>
#include "mini.h"
return mono_main (argc, argv);
}
-#define STREAM_INT(x) (*(uint32_t*)x)
-#define STREAM_LONG(x) (*(uint64_t*)x)
+#define STREAM_INT(x) GUINT32_TO_LE((*(uint32_t*)x))
+#define STREAM_LONG(x) GUINT64_TO_LE((*(uint64_t*)x))
+
+/**
+ * Loads a chunk of data from the file pointed to by the
+ * @fd starting at the file offset @offset for @size bytes
+ * and returns an allocated version of that string, or NULL
+ * on error.
+ */
+static char *
+load_from_region (int fd, uint64_t offset, uint64_t size)
+{
+ char *buffer;
+ off_t loc;
+ int status;
+
+ do {
+ loc = lseek (fd, offset, SEEK_SET);
+ } while (loc == -1 && errno == EINTR);
+ if (loc == -1)
+ return NULL;
+ buffer = g_malloc (size + 1);
+ if (buffer == NULL)
+ return NULL;
+ buffer [size] = 0;
+ do {
+ status = read (fd, buffer, size);
+ } while (status == -1 && errno == EINTR);
+ if (status == -1){
+ g_free (buffer);
+ return NULL;
+ }
+ return buffer;
+}
static gboolean
probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
char *config = kind + strlen ("config:");
char *aname = g_strdup (config);
aname [strlen(aname)-strlen(".config")] = 0;
- mono_register_config_for_assembly (aname, config);
- } else if (strncmp (kind, "system_config:", strlen ("system_config:")) == 0){
- printf ("TODO s-Found: %s %llx\n", kind, (long long)offset);
+ mono_register_config_for_assembly (aname, load_from_region (fd, offset, item_size));
+ } else if (strncmp (kind, "systemconfig:", strlen ("systemconfig:")) == 0){
+ mono_config_parse_memory (load_from_region (fd, offset, item_size));
} else if (strncmp (kind, "options:", strlen ("options:")) == 0){
- mono_parse_options_from (kind + strlen("options:"), ref_argc, ref_argv);
+ mono_parse_options_from (load_from_region (fd, offset, item_size), ref_argc, ref_argv);
} else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){
- printf ("TODO Found: %s %llx\n", kind, (long long)offset);
+ mono_set_dirs (getenv ("MONO_PATH"), load_from_region (fd, offset, item_size));
+ } else if (strncmp (kind, "machineconfig:", strlen ("machineconfig:")) == 0) {
+ mono_register_machine_config (load_from_region (fd, offset, item_size));
+ } else if (strncmp (kind, "env:", strlen ("env:")) == 0){
+ char *data = load_from_region (fd, offset, item_size);
+ uint8_t count = *data++;
+ char *value = data + count + 1;
+ g_setenv (data, value, FALSE);
} else {
fprintf (stderr, "Unknown stream on embedded package: %s\n", kind);
exit (1);
return FALSE;
}
+static gboolean
+method_needs_stack_walk (MonoCompile *cfg, MonoMethod *cmethod)
+{
+ if (cmethod->klass == mono_defaults.systemtype_class) {
+ if (!strcmp (cmethod->name, "GetType"))
+ return TRUE;
+ }
+ return FALSE;
+}
+
#define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
static MonoInst*
}
if (!has_vtargs) {
+ if (need_seq_point) {
+ emit_seq_point (cfg, method, ip, FALSE, TRUE);
+ need_seq_point = FALSE;
+ }
for (i = 0; i < n; ++i)
EMIT_NEW_ARGSTORE (cfg, ins, i, sp [i]);
MONO_INST_NEW (cfg, ins, OP_BR);
EMIT_NEW_DUMMY_USE (cfg, dummy_use, keep_this_alive);
}
+ if (cfg->llvm_only && cmethod && method_needs_stack_walk (cfg, cmethod)) {
+ /*
+ * Clang can convert these calls to tail calls which screw up the stack
+ * walk. This happens even when the -fno-optimize-sibling-calls
+ * option is passed to clang.
+ * Work around this by emitting a dummy call.
+ */
+ mono_emit_jit_icall (cfg, mono_dummy_jit_icall, NULL);
+ }
+
CHECK_CFG_EXCEPTION;
ip += 5;
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-tls.h>
-#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "trace.h"
info->fields [i].mspec,
&align, TRUE, unicode);
fields [index].offset = offset + info->fields [i].offset;
+ if (i == info->num_fields - 1 && fields [index].size + fields [index].offset < info->native_size) {
+ /* This can happen with .pack directives eg. 'fixed' arrays */
+ fields [index].size = info->native_size - fields [index].offset;
+ }
index ++;
}
}
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-arm.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads-coop.h>
static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data);
static void mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx);
static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data);
+static gboolean mono_current_thread_has_handle_block_guard (void);
void
mono_exceptions_init (void)
cbs.mono_raise_exception_with_ctx = mono_raise_exception_with_ctx;
cbs.mono_exception_walk_trace = mono_exception_walk_trace;
cbs.mono_install_handler_block_guard = mono_install_handler_block_guard;
+ cbs.mono_current_thread_has_handle_block_guard = mono_current_thread_has_handle_block_guard;
mono_install_eh_callbacks (&cbs);
}
return TRUE;
}
+static gboolean
+mono_current_thread_has_handle_block_guard (void)
+{
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ return jit_tls && jit_tls->handler_block_return_address != NULL;
+}
+
#else
gboolean
mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
return FALSE;
}
+static gboolean
+mono_current_thread_has_handle_block_guard (void)
+{
+ return FALSE;
+}
+
#endif
void
#include <mono/metadata/threads.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap-ia64.h>
+#include <mono/utils/mono-hwcap.h>
#include "trace.h"
#include "mini-ia64.h"
values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
break;
}
+
+/*
+ * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
+ * hack is necessary (for now).
+ */
+#ifdef TARGET_ARM64
+#define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
+#else
+#define ARM64_ATOMIC_FENCE_FIX
+#endif
+
case OP_ATOMIC_EXCHANGE_I4:
case OP_ATOMIC_EXCHANGE_I8: {
LLVMValueRef args [2];
args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
args [1] = convert (ctx, rhs, t);
+ ARM64_ATOMIC_FENCE_FIX;
values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
+ ARM64_ATOMIC_FENCE_FIX;
break;
}
case OP_ATOMIC_ADD_I4:
args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
args [1] = convert (ctx, rhs, t);
+ ARM64_ATOMIC_FENCE_FIX;
values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
+ ARM64_ATOMIC_FENCE_FIX;
break;
}
case OP_ATOMIC_CAS_I4:
args [1] = convert (ctx, values [ins->sreg3], t);
/* new value */
args [2] = convert (ctx, values [ins->sreg2], t);
+ ARM64_ATOMIC_FENCE_FIX;
val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
+ ARM64_ATOMIC_FENCE_FIX;
/* cmpxchg returns a pair */
values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
break;
addr = convert (ctx, addr, LLVMPointerType (t, 0));
+ ARM64_ATOMIC_FENCE_FIX;
values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
+ ARM64_ATOMIC_FENCE_FIX;
if (sext)
values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
value = convert (ctx, values [ins->sreg1], t);
+ ARM64_ATOMIC_FENCE_FIX;
emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
+ ARM64_ATOMIC_FENCE_FIX;
break;
}
case OP_RELAXED_NOP: {
ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
// FIXME: beforefieldinit
- if (ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) {
+ /*
+ * NATIVE_TO_MANAGED methods might be called on a thread not attached to the runtime, so they are initialized when loaded
+ * in load_method ().
+ */
+ if ((ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) && !(cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
/*
* linkonce methods shouldn't have initialization,
* because they might belong to assemblies which
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-mips.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/arch/mips/mips-codegen.h>
if (strcmp ("nfloat", klass->name) == 0) {
magic_nfloat_class = klass;
+
+ /* Assert that we are using the matching assembly */
+ MonoClassField *value_field = mono_class_get_field_from_name (klass, "v");
+ g_assert (value_field);
+ MonoType *t = mono_field_get_type (value_field);
+ g_assert (t->type == mini_native_type_replace_type (&klass->byval_arg)->type);
+
return TRUE;
}
return FALSE;
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-ppc.h>
+#include <mono/utils/mono-hwcap.h>
#include "mini-ppc.h"
#ifdef TARGET_POWERPC64
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/checked-build.h>
+#include <mono/utils/w32handle.h>
#include <mono/io-layer/io-layer.h>
#include "mini.h"
runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
runtime_invoke (NULL, args, exc, info->compiled_method);
- if (exc && *exc) {
- mono_error_set_exception_instance (error, (MonoException*) *exc);
+ if (exc && *exc)
return NULL;
- }
if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
return mono_value_box_checked (domain, info->ret_box_class, retval, error);
}
#endif
- if (mono_llvm_only)
- return mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
+ MonoObject *result;
- runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
+ if (mono_llvm_only) {
+ result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
+ if (!is_ok (error))
+ return NULL;
+ } else {
+ runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
- MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ }
if (catchExcInMonoError && *exc != NULL)
mono_error_set_exception_instance (error, (MonoException*) *exc);
return result;
mono_counters_init ();
+#ifndef HOST_WIN32
+ mono_w32handle_init ();
+#endif
+
mono_threads_runtime_init (&ticallbacks);
if (g_getenv ("MONO_DEBUG") != NULL)
register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
+ register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
register_icall_with_wrapper (mono_monitor_enter, "mono_monitor_enter", "void obj");
register_icall_with_wrapper (mono_monitor_enter_v4, "mono_monitor_enter_v4", "void obj ptr");
mono_os_mutex_destroy (&jit_mutex);
mono_code_manager_cleanup ();
+
+#ifndef HOST_WIN32
+ mono_w32handle_cleanup ();
+#endif
}
void
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-s390x.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "mini-s390x.h"
gboolean lmf_addr_key_inited = FALSE;
-facilityList_t facs;
-
/*
* The code generated for sequence points reads from this location,
* which is made read-only when single stepping is enabled.
}
break;
case OP_ICONV_TO_R_UN: {
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
s390_llgfr (code, s390_r0, ins->sreg1);
}
break;
case OP_LCONV_TO_R_UN: {
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
short int *jump;
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U1:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
s390_lghi (code, s390_r0, 0xff);
s390_ngr (code, ins->dreg, s390_r0);
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U2:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
s390_llill (code, s390_r0, 0xffff);
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U4:
case OP_FCONV_TO_U:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
break;
case OP_FCONV_TO_U8:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
{
guint32 sseOpts = 0;
- if (facs.vec != 0)
+ if (mono_hwcap_s390x_has_vec)
sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/tokentype.h>
#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap-sparc.h>
+#include <mono/utils/mono-hwcap.h>
#include "mini-sparc.h"
#include "trace.h"
--- /dev/null
+/*
+ * mini-windows-dllmain.c: DllMain entry point.
+ *
+ * (C) 2002-2003 Ximian, Inc.
+ * (C) 2003-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <mono/metadata/coree.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/utils/mono-threads.h>
+#include "mini.h"
+
+#ifdef HOST_WIN32
+#include <windows.h>
+
+BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
+{
+ if (!mono_gc_dllmain (module_handle, reason, reserved))
+ return FALSE;
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ mono_install_runtime_load (mini_init);
+ break;
+ case DLL_PROCESS_DETACH:
+ if (coree_module_handle)
+ FreeLibrary (coree_module_handle);
+ break;
+ case DLL_THREAD_DETACH:
+ mono_thread_info_detach ();
+ break;
+
+ }
+ return TRUE;
+}
+#endif
+
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-memory-model.h>
-#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "trace.h"
#define MONO_IS_SETCC(ins) ((((ins)->opcode >= OP_CEQ) && ((ins)->opcode <= OP_CLT_UN)) || (((ins)->opcode >= OP_ICEQ) && ((ins)->opcode <= OP_ICLE_UN)) || (((ins)->opcode >= OP_LCEQ) && ((ins)->opcode <= OP_LCLT_UN)) || (((ins)->opcode >= OP_FCEQ) && ((ins)->opcode <= OP_FCLT_UN)))
+#define MONO_HAS_CUSTOM_EMULATION(ins) (((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_FCEQ && (ins)->opcode <= OP_FCLT_UN))
#define MONO_IS_LOAD_MEMBASE(ins) (((ins)->opcode >= OP_LOAD_MEMBASE && (ins)->opcode <= OP_LOADV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_LOAD_I1 && (ins)->opcode <= OP_ATOMIC_LOAD_R8))
#define MONO_IS_STORE_MEMBASE(ins) (((ins)->opcode >= OP_STORE_MEMBASE_REG && (ins)->opcode <= OP_STOREV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_STORE_I1 && (ins)->opcode <= OP_ATOMIC_STORE_R8))
{
guint32 ins = ((guint32*)(gpointer)code) [-1];
-#if MONOTOUCH
/* Should be a 'bl' or a 'b' */
if (((ins >> 25) & 0x7) == 0x5) {
-#else
- /* Should be a 'bl' */
- if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) {
-#endif
gint32 disp = ((((gint32)ins) & 0xffffff) << 8) >> 8;
guint8 *target = code - 4 + 8 + (disp * 4);
int timer_overhead;
int pid;
int port;
+ char *args;
+ char *arch;
+ char *os;
uint64_t startup_time;
ThreadContext *threads;
ThreadContext *current_thread;
case MONO_GC_EVENT_RECLAIM_END: return "reclaim end";
case MONO_GC_EVENT_END: return "end";
case MONO_GC_EVENT_PRE_STOP_WORLD: return "pre stop";
+ case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED: return "pre stop lock";
case MONO_GC_EVENT_POST_STOP_WORLD: return "post stop";
case MONO_GC_EVENT_PRE_START_WORLD: return "pre start";
case MONO_GC_EVENT_POST_START_WORLD: return "post start";
+ case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED: return "post start unlock";
+ default:
+ return "unknown";
+ }
+}
+
+static const char*
+sync_point_name (int type)
+{
+ switch (type) {
+ case SYNC_POINT_PERIODIC: return "periodic";
+ case SYNC_POINT_WORLD_STOP: return "world stop";
+ case SYNC_POINT_WORLD_START: return "world start";
default:
return "unknown";
}
}
static MethodDesc**
-decode_bt (MethodDesc** sframes, int *size, unsigned char *p, unsigned char **endp, intptr_t ptr_base)
+decode_bt (ProfContext *ctx, MethodDesc** sframes, int *size, unsigned char *p, unsigned char **endp, intptr_t ptr_base, intptr_t *method_base)
{
MethodDesc **frames;
int i;
- int flags = decode_uleb128 (p, &p);
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
int count = decode_uleb128 (p, &p);
- if (flags != 0)
- return NULL;
if (count > *size)
frames = (MethodDesc **)malloc (count * sizeof (void*));
else
frames = sframes;
for (i = 0; i < count; ++i) {
intptr_t ptrdiff = decode_sleb128 (p, &p);
- frames [i] = lookup_method (ptr_base + ptrdiff);
+ if (ctx->data_version > 12) {
+ *method_base += ptrdiff;
+ frames [i] = lookup_method (*method_base);
+ } else {
+ frames [i] = lookup_method (ptr_base + ptrdiff);
+ }
}
*size = count;
*endp = p;
if (new_size > max_heap_size)
max_heap_size = new_size;
} else if (subtype == TYPE_GC_EVENT) {
- uint64_t ev = decode_uleb128 (p, &p);
- int gen = decode_uleb128 (p, &p);
+ uint64_t ev;
+ if (ctx->data_version > 12)
+ ev = *p++;
+ else
+ ev = decode_uleb128 (p, &p);
+ int gen;
+ if (ctx->data_version > 12)
+ gen = *p++;
+ else
+ gen = decode_uleb128 (p, &p);
if (debug)
fprintf (outfile, "gc event for gen%d: %s at %llu (thread: 0x%zx)\n", gen, gc_event_name (ev), (unsigned long long) time_base, thread->thread_id);
if (gen > 2) {
intptr_t objdiff = decode_sleb128 (p, &p);
if (has_bt) {
num_bt = 8;
- frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+ frames = decode_bt (ctx, sframes, &num_bt, p, &p, ptr_base, &method_base);
if (!frames) {
fprintf (outfile, "Cannot load backtrace\n");
return 0;
uint32_t handle = decode_uleb128 (p, &p);
if (has_bt) {
num_bt = 8;
- frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+ frames = decode_bt (ctx, sframes, &num_bt, p, &p, ptr_base, &method_base);
if (!frames) {
fprintf (outfile, "Cannot load backtrace\n");
return 0;
fprintf (outfile, "handle (%s) %u destroyed\n", get_handle_name (htype), handle);
if (frames != sframes)
free (frames);
+ } else if (subtype == TYPE_GC_FINALIZE_START) {
+ // TODO: Generate a finalizer report based on these events.
+ if (debug)
+ fprintf (outfile, "gc finalizer queue being processed at %llu\n", (unsigned long long) time_base);
+ } else if (subtype == TYPE_GC_FINALIZE_END) {
+ if (debug)
+ fprintf (outfile, "gc finalizer queue finished processing at %llu\n", (unsigned long long) time_base);
+ } else if (subtype == TYPE_GC_FINALIZE_OBJECT_START) {
+ intptr_t objdiff = decode_sleb128 (p, &p);
+ if (debug)
+ fprintf (outfile, "gc finalizing object %p at %llu\n", (void *) OBJ_ADDR (objdiff), (unsigned long long) time_base);
+ } else if (subtype == TYPE_GC_FINALIZE_OBJECT_END) {
+ intptr_t objdiff = decode_sleb128 (p, &p);
+ if (debug)
+ fprintf (outfile, "gc finalized object %p at %llu\n", (void *) OBJ_ADDR (objdiff), (unsigned long long) time_base);
}
break;
}
time_base += tdiff;
if (mtype == TYPE_CLASS) {
intptr_t imptrdiff = decode_sleb128 (p, &p);
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in class\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
if (debug)
fprintf (outfile, "%s class %p (%s in %p) at %llu\n", load_str, (void*)(ptr_base + ptrdiff), p, (void*)(ptr_base + imptrdiff), (unsigned long long) time_base);
if (subtype == TYPE_END_LOAD)
while (*p) p++;
p++;
} else if (mtype == TYPE_IMAGE) {
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in image\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
if (debug)
fprintf (outfile, "%s image %p (%s) at %llu\n", load_str, (void*)(ptr_base + ptrdiff), p, (unsigned long long) time_base);
if (subtype == TYPE_END_LOAD)
while (*p) p++;
p++;
} else if (mtype == TYPE_ASSEMBLY) {
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in assembly\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
if (debug)
fprintf (outfile, "%s assembly %p (%s) at %llu\n", load_str, (void*)(ptr_base + ptrdiff), p, (unsigned long long) time_base);
if (subtype == TYPE_END_LOAD)
while (*p) p++;
p++;
} else if (mtype == TYPE_DOMAIN) {
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in domain\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
DomainContext *nd = get_domain (ctx, ptr_base + ptrdiff);
/* no subtype means it's a name event, rather than start/stop */
if (subtype == 0)
p++;
}
} else if (mtype == TYPE_CONTEXT) {
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in context\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
intptr_t domaindiff = decode_sleb128 (p, &p);
if (debug)
fprintf (outfile, "%s context %p (%p) at %llu\n", load_str, (void*)(ptr_base + ptrdiff), (void *) (ptr_base + domaindiff), (unsigned long long) time_base);
if (subtype == TYPE_END_LOAD)
get_remctx (ctx, ptr_base + ptrdiff)->domain_id = ptr_base + domaindiff;
} else if (mtype == TYPE_THREAD) {
- uint64_t flags = decode_uleb128 (p, &p);
- if (flags) {
- fprintf (outfile, "non-zero flags in thread\n");
- return 0;
- }
+ if (ctx->data_version < 13)
+ decode_uleb128 (p, &p); /* flags */
ThreadContext *nt = get_thread (ctx, ptr_base + ptrdiff);
/* no subtype means it's a name event, rather than start/stop */
if (subtype == 0)
fprintf (outfile, "alloced object %p, size %llu (%s) at %llu\n", (void*)OBJ_ADDR (objdiff), (unsigned long long) len, lookup_class (ptr_base + ptrdiff)->name, (unsigned long long) time_base);
if (has_bt) {
num_bt = 8;
- frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+ frames = decode_bt (ctx, sframes, &num_bt, p, &p, ptr_base, &method_base);
if (!frames) {
fprintf (outfile, "Cannot load backtrace\n");
return 0;
if (subtype == TYPE_HEAP_OBJECT) {
HeapObjectDesc *ho = NULL;
int i;
- intptr_t objdiff = decode_sleb128 (p + 1, &p);
+ intptr_t objdiff;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ objdiff = decode_sleb128 (p, &p);
+ } else
+ objdiff = decode_sleb128 (p + 1, &p);
intptr_t ptrdiff = decode_sleb128 (p, &p);
uint64_t size = decode_uleb128 (p, &p);
uintptr_t num = decode_uleb128 (p, &p);
if (debug && size)
fprintf (outfile, "traced object %p, size %llu (%s), refs: %zd\n", (void*)OBJ_ADDR (objdiff), (unsigned long long) size, cd->name, num);
} else if (subtype == TYPE_HEAP_ROOT) {
- uintptr_t num = decode_uleb128 (p + 1, &p);
+ uintptr_t num;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ num = decode_uleb128 (p, &p);
+ } else
+ num = decode_uleb128 (p + 1, &p);
uintptr_t gc_num G_GNUC_UNUSED = decode_uleb128 (p, &p);
int i;
for (i = 0; i < num; ++i) {
intptr_t objdiff = decode_sleb128 (p, &p);
- int root_type = decode_uleb128 (p, &p);
+ int root_type;
+ if (ctx->data_version > 12)
+ root_type = *p++;
+ else
+ root_type = decode_uleb128 (p, &p);
/* we just discard the extra info for now */
uintptr_t extra_info = decode_uleb128 (p, &p);
if (debug)
}
if (has_bt) {
num_bt = 8;
- frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+ frames = decode_bt (ctx, sframes, &num_bt, p, &p, ptr_base, &method_base);
if (!frames) {
fprintf (outfile, "Cannot load backtrace\n");
return 0;
}
case TYPE_EXCEPTION: {
int subtype = *p & 0x70;
- int has_bt = *p & TYPE_EXCEPTION_BT;
+ int has_bt = *p & TYPE_THROW_BT;
uint64_t tdiff = decode_uleb128 (p + 1, &p);
MethodDesc* sframes [8];
MethodDesc** frames = sframes;
if (!(time_base >= time_from && time_base < time_to))
record = 0;
if (subtype == TYPE_CLAUSE) {
- int clause_type = decode_uleb128 (p, &p);
+ int clause_type;
+ if (ctx->data_version > 12)
+ clause_type = *p++;
+ else
+ clause_type = decode_uleb128 (p, &p);
int clause_num = decode_uleb128 (p, &p);
int64_t ptrdiff = decode_sleb128 (p, &p);
method_base += ptrdiff;
throw_count++;
if (has_bt) {
has_bt = 8;
- frames = decode_bt (sframes, &has_bt, p, &p, ptr_base);
+ frames = decode_bt (ctx, sframes, &has_bt, p, &p, ptr_base, &method_base);
if (!frames) {
fprintf (outfile, "Cannot load backtrace\n");
return 0;
LOG_TIME (time_base, tdiff);
time_base += tdiff;
if (subtype == TYPE_JITHELPER) {
- int type = decode_uleb128 (p, &p);
+ int type;
+ if (ctx->data_version > 12)
+ type = *p++;
+ else
+ type = decode_uleb128 (p, &p);
intptr_t codediff = decode_sleb128 (p, &p);
int codelen = decode_uleb128 (p, &p);
const char *name;
int subtype = *p & 0xf0;
if (subtype == TYPE_SAMPLE_HIT) {
int i;
- int sample_type = decode_uleb128 (p + 1, &p);
- uint64_t tstamp = decode_uleb128 (p, &p);
+ int sample_type;
+ uint64_t tstamp;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ sample_type = *p++;
+ tstamp = time_base;
+ } else {
+ sample_type = decode_uleb128 (p + 1, &p);
+ tstamp = decode_uleb128 (p, &p);
+ }
void *tid = (void *) thread_id;
if (ctx->data_version > 10)
tid = (void *) (ptr_base + decode_sleb128 (p, &p));
for (i = 0; i < count; ++i) {
MethodDesc *method;
int64_t ptrdiff = decode_sleb128 (p, &p);
- int il_offset = decode_sleb128 (p, &p);
- int native_offset = decode_sleb128 (p, &p);
method_base += ptrdiff;
method = lookup_method (method_base);
if (debug)
- fprintf (outfile, "sample hit bt %d: %s at IL offset %d (native: %d)\n", i, method->name, il_offset, native_offset);
+ fprintf (outfile, "sample hit bt %d: %s\n", i, method->name);
+ if (ctx->data_version < 13) {
+ decode_sleb128 (p, &p); /* il offset */
+ decode_sleb128 (p, &p); /* native offset */
+ }
}
}
} else if (subtype == TYPE_SAMPLE_USYM) {
/* un unmanaged symbol description */
- uintptr_t addr = ptr_base + decode_sleb128 (p + 1, &p);
+ uintptr_t addr;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ addr = ptr_base + decode_sleb128 (p, &p);
+ } else
+ addr = ptr_base + decode_sleb128 (p + 1, &p);
uintptr_t size = decode_uleb128 (p, &p);
char *name;
name = pstrdup ((char*)p);
while (*p) p++;
p++;
} else if (subtype == TYPE_SAMPLE_COUNTERS_DESC) {
- uint64_t i, len = decode_uleb128 (p + 1, &p);
+ uint64_t i, len;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ len = decode_uleb128 (p, &p);
+ } else
+ len = decode_uleb128 (p + 1, &p);
for (i = 0; i < len; i++) {
uint64_t type, unit, variance, index;
uint64_t section = decode_uleb128 (p, &p);
}
name = pstrdup ((char*)p);
while (*p++);
- type = decode_uleb128 (p, &p);
- unit = decode_uleb128 (p, &p);
- variance = decode_uleb128 (p, &p);
+ if (ctx->data_version > 12) {
+ type = *p++;
+ unit = *p++;
+ variance = *p++;
+ } else {
+ type = decode_uleb128 (p, &p);
+ unit = decode_uleb128 (p, &p);
+ variance = decode_uleb128 (p, &p);
+ }
index = decode_uleb128 (p, &p);
add_counter (section_str, name, (int)type, (int)unit, (int)variance, (int)index);
}
int i;
CounterValue *value, *previous = NULL;
CounterList *list;
- uint64_t timestamp = decode_uleb128 (p + 1, &p);
+ uint64_t timestamp; // milliseconds since startup
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ timestamp = (time_base - startup_time) / 1000 / 1000;
+ } else
+ timestamp = decode_uleb128 (p + 1, &p);
uint64_t time_between = timestamp / 1000 * 1000 * 1000 * 1000 + startup_time;
while (1) {
uint64_t type, index = decode_uleb128 (p, &p);
}
}
- type = decode_uleb128 (p, &p);
+ if (ctx->data_version > 12)
+ type = *p++;
+ else
+ type = decode_uleb128 (p, &p);
value = (CounterValue *)calloc (1, sizeof (CounterValue));
value->timestamp = timestamp;
int token, n_offsets, method_id;
p++;
+
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ }
+
assembly = (const char *)p; while (*p) p++; p++;
klass = (const char *)p; while (*p) p++; p++;
name = (const char *)p; while (*p) p++; p++;
int offset, count, line, column, method_id;
p++;
+
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ }
+
method_id = decode_uleb128 (p, &p);
offset = decode_uleb128 (p, &p);
count = decode_uleb128 (p, &p);
int number_of_methods, fully_covered, partially_covered;
p++;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ }
+
name = (char *)p; while (*p) p++; p++;
guid = (char *)p; while (*p) p++; p++;
filename = (char *)p; while (*p) p++; p++;
int number_of_methods, fully_covered, partially_covered;
p++;
+ if (ctx->data_version > 12) {
+ uint64_t tdiff = decode_uleb128 (p, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ }
+
assembly_name = (char *)p; while (*p) p++; p++;
class_name = (char *)p; while (*p) p++; p++;
number_of_methods = decode_uleb128 (p, &p);
}
break;
}
+ case TYPE_META: {
+ int subtype = *p & 0xf0;
+ uint64_t tdiff = decode_uleb128 (p + 1, &p);
+ LOG_TIME (time_base, tdiff);
+ time_base += tdiff;
+ if (subtype == TYPE_SYNC_POINT) {
+ int type = *p++;
+ if (debug)
+ fprintf (outfile, "sync point %i (%s)\n", type, sync_point_name (type));
+ }
+ break;
+ }
default:
fprintf (outfile, "unhandled profiler event: 0x%x at file offset: %llu + %lld (len: %d\n)\n", *p, (unsigned long long) file_offset, (long long) (p - ctx->buf), len);
exit (1);
return 1;
}
+static int
+read_header_string (ProfContext *ctx, char **field)
+{
+ if (!load_data (ctx, 4))
+ return 0;
+
+ if (!load_data (ctx, read_int32 (ctx->buf)))
+ return 0;
+
+ *field = pstrdup ((const char *) ctx->buf);
+
+ return 1;
+}
+
static ProfContext*
load_file (char *name)
{
if (ctx->file != stdin)
ctx->gzfile = gzdopen (fileno (ctx->file), "rb");
#endif
- if (!load_data (ctx, 32))
+ if (!load_data (ctx, 30))
return NULL;
p = ctx->buf;
if (read_int32 (p) != LOG_HEADER_ID || p [6] > LOG_DATA_VERSION)
ctx->timer_overhead = read_int32 (p + 16);
ctx->pid = read_int32 (p + 24);
ctx->port = read_int16 (p + 28);
+ if (ctx->version_major >= 1) {
+ if (!read_header_string (ctx, &ctx->args))
+ return NULL;
+ if (!read_header_string (ctx, &ctx->arch))
+ return NULL;
+ if (!read_header_string (ctx, &ctx->os))
+ return NULL;
+ } else {
+ if (!load_data (ctx, 2)) /* old opsys field, was never used */
+ return NULL;
+ }
return ctx;
}
fprintf (outfile, "\nMono log profiler data\n");
fprintf (outfile, "\tProfiler version: %d.%d\n", ctx->version_major, ctx->version_minor);
fprintf (outfile, "\tData version: %d\n", ctx->data_version);
+ if (ctx->version_major >= 1) {
+ fprintf (outfile, "\tArguments: %s\n", ctx->args);
+ fprintf (outfile, "\tArchitecture: %s\n", ctx->arch);
+ fprintf (outfile, "\tOperating system: %s\n", ctx->os);
+ }
fprintf (outfile, "\tMean timer overhead: %d nanoseconds\n", ctx->timer_overhead);
fprintf (outfile, "\tProgram startup: %s", t);
if (ctx->pid)
DUMP_EVENT_STAT (TYPE_METHOD, TYPE_EXC_LEAVE);
DUMP_EVENT_STAT (TYPE_METHOD, TYPE_JIT);
- DUMP_EVENT_STAT (TYPE_EXCEPTION, TYPE_THROW);
+ DUMP_EVENT_STAT (TYPE_EXCEPTION, TYPE_THROW_NO_BT);
+ DUMP_EVENT_STAT (TYPE_EXCEPTION, TYPE_THROW_BT);
DUMP_EVENT_STAT (TYPE_EXCEPTION, TYPE_CLAUSE);
- DUMP_EVENT_STAT (TYPE_EXCEPTION, TYPE_EXCEPTION_BT);
DUMP_EVENT_STAT (TYPE_MONITOR, TYPE_MONITOR_NO_BT);
DUMP_EVENT_STAT (TYPE_MONITOR, TYPE_MONITOR_BT);
DUMP_EVENT_STAT (TYPE_COVERAGE, TYPE_COVERAGE_METHOD);
DUMP_EVENT_STAT (TYPE_COVERAGE, TYPE_COVERAGE_STATEMENT);
DUMP_EVENT_STAT (TYPE_COVERAGE, TYPE_COVERAGE_CLASS);
+
+ DUMP_EVENT_STAT (TYPE_META, TYPE_SYNC_POINT);
}
#include "../metadata/metadata-internals.h"
#include <mono/metadata/profiler.h>
#include <mono/metadata/threads.h>
-#include <mono/metadata/mono-gc.h>
#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/mono-gc.h>
#include <mono/metadata/mono-perfcounters.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/assembly.h>
#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-os-semaphore.h>
#include <mono/utils/mono-conc-hashtable.h>
+#include <mono/utils/mono-linked-list-set.h>
#include <mono/utils/lock-free-alloc.h>
#include <mono/utils/lock-free-queue.h>
#include <mono/utils/hazard-pointer.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-api.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
#define LEB128_SIZE 10
-/* Size in bytes of the event ID prefix. */
-#define EVENT_SIZE 1
+/* Size of a value encoded as a single byte. */
+#define BYTE_SIZE 1
+/* Size in bytes of the event prefix (ID + time). */
+#define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
static int nocalls = 0;
static int notraces = 0;
static gint32 class_loads;
static gint32 class_unloads;
-typedef struct _LogBuffer LogBuffer;
+static MonoLinkedListSet profiler_thread_list;
/*
* file format:
* [flags: 4 bytes] file format flags, should be 0 for now
* [pid: 4 bytes] pid of the profiled process
* [port: 2 bytes] tcp port for server if != 0
- * [sysid: 2 bytes] operating system and architecture identifier
+ * [args size: 4 bytes] size of args
+ * [args: string] arguments passed to the profiler
+ * [arch size: 4 bytes] size of arch
+ * [arch: string] architecture the profiler is running on
+ * [os size: 4 bytes] size of os
+ * [os: string] operating system the profiler is running on
*
* The multiple byte integers are in little-endian format.
*
* [method_base: 8 bytes] base value for MonoMethod pointers
*
* event format:
- * [extended info: upper 4 bits] [type: lower 4 bits] [data]*
+ * [extended info: upper 4 bits] [type: lower 4 bits]
+ * [time diff: uleb128] nanoseconds since last timing
+ * [data]*
* The data that follows depends on type and the extended info.
* Type is one of the enum values in proflog.h: TYPE_ALLOC, TYPE_GC,
* TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
* strings are represented as a 0-terminated utf8 sequence.
*
* backtrace format:
- * [flags: uleb128] must be 0
* [num: uleb128] number of frames following
- * [frame: sleb128]* num MonoMethod pointers as differences from ptr_base
+ * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
*
* type alloc format:
* type: TYPE_ALLOC
* exinfo: flags: TYPE_ALLOC_BT
- * [time diff: uleb128] nanoseconds since last timing
* [ptr: sleb128] class as a byte difference from ptr_base
* [obj: sleb128] object address as a byte difference from obj_base
* [size: uleb128] size of the object in the heap
* type GC format:
* type: TYPE_GC
* exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
- * TYPE_GC_HANDLE_DESTROYED[_BT]
- * [time diff: uleb128] nanoseconds since last timing
+ * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
+ * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
* if exinfo == TYPE_GC_RESIZE
* [heap_size: uleb128] new heap size
* if exinfo == TYPE_GC_EVENT
- * [event type: uleb128] GC event (MONO_GC_EVENT_* from profiler.h)
- * [generation: uleb128] GC generation event refers to
+ * [event type: byte] GC event (MONO_GC_EVENT_* from profiler.h)
+ * [generation: byte] GC generation event refers to
* if exinfo == TYPE_GC_MOVE
* [num_objects: uleb128] number of object moves that follow
* [objaddr: sleb128]+ num_objects object pointer differences from obj_base
* upper bits reserved as flags
* [handle: uleb128] GC handle value
* If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_FINALIZE_OBJECT_{START,END}
+ * [object: sleb128] the object as a difference from obj_base
*
* type metadata format:
* type: TYPE_METADATA
* exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN)
- * [time diff: uleb128] nanoseconds since last timing
* [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
* TYPE_THREAD, TYPE_CONTEXT
* [pointer: sleb128] pointer of the metadata type depending on mtype
* if mtype == TYPE_CLASS
* [image: sleb128] MonoImage* as a pointer difference from ptr_base
- * [flags: uleb128] must be 0
* [name: string] full class name
* if mtype == TYPE_IMAGE
- * [flags: uleb128] must be 0
* [name: string] image file name
* if mtype == TYPE_ASSEMBLY
- * [flags: uleb128] must be 0
* [name: string] assembly name
- * if mtype == TYPE_DOMAIN
- * [flags: uleb128] must be 0
* if mtype == TYPE_DOMAIN && exinfo == 0
* [name: string] domain friendly name
* if mtype == TYPE_CONTEXT
- * [flags: uleb128] must be 0
* [domain: sleb128] domain id as pointer
- * if mtype == TYPE_THREAD && (format_version < 11 || (format_version > 10 && exinfo == 0))
- * [flags: uleb128] must be 0
+ * if mtype == TYPE_THREAD && exinfo == 0
* [name: string] thread name
*
* type method format:
* type: TYPE_METHOD
* exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
- * [time diff: uleb128] nanoseconds since last timing
* [method: sleb128] MonoMethod* as a pointer difference from the last such
* pointer or the buffer method_base
* if exinfo == TYPE_JIT
* [code size: uleb128] size of the generated code
* [name: string] full method name
*
+ * type exception format:
+ * type: TYPE_EXCEPTION
+ * exinfo: TYPE_THROW_BT flag or one of: TYPE_CLAUSE
+ * if exinfo == TYPE_CLAUSE
+ * [clause type: byte] MonoExceptionEnum enum value
+ * [clause index: uleb128] index of the current clause
+ * [method: sleb128] MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ * else
+ * [object: sleb128] the exception object as a difference from obj_base
+ * if exinfo has TYPE_THROW_BT set, a backtrace follows.
+ *
* type runtime format:
* type: TYPE_RUNTIME
* exinfo: one of: TYPE_JITHELPER
- * [time diff: uleb128] nanoseconds since last timing
* if exinfo == TYPE_JITHELPER
- * [type: uleb128] MonoProfilerCodeBufferType enum value
+ * [type: byte] MonoProfilerCodeBufferType enum value
* [buffer address: sleb128] pointer to the native code as a diff from ptr_base
* [buffer size: uleb128] size of the generated code
* if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
* type monitor format:
* type: TYPE_MONITOR
* exinfo: TYPE_MONITOR_BT flag and one of: MONO_PROFILER_MONITOR_(CONTENTION|FAIL|DONE)
- * [time diff: uleb128] nanoseconds since last timing
* [object: sleb128] the lock object as a difference from obj_base
* if exinfo.low3bits == MONO_PROFILER_MONITOR_CONTENTION
* If the TYPE_MONITOR_BT flag is set, a backtrace follows.
* type heap format
* type: TYPE_HEAP
* exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
- * if exinfo == TYPE_HEAP_START
- * [time diff: uleb128] nanoseconds since last timing
- * if exinfo == TYPE_HEAP_END
- * [time diff: uleb128] nanoseconds since last timing
* if exinfo == TYPE_HEAP_OBJECT
* [object: sleb128] the object as a difference from obj_base
* [class: sleb128] the object MonoClass* as a difference from ptr_base
* [size: uleb128] size of the object on the heap
* [num_refs: uleb128] number of object references
- * if (format version > 1) each referenced objref is preceded by a
- * uleb128 encoded offset: the first offset is from the object address
- * and each next offset is relative to the previous one
+ * each referenced objref is preceded by a uleb128 encoded offset: the
+ * first offset is from the object address and each next offset is relative
+ * to the previous one
* [objrefs: sleb128]+ object referenced as a difference from obj_base
* The same object can appear multiple times, but only the first time
* with size != 0: in the other cases this data will only be used to
* [num_roots: uleb128] number of root references
* [num_gc: uleb128] number of major gcs
* [object: sleb128] the object as a difference from obj_base
- * [root_type: uleb128] the root_type: MonoProfileGCRootType (profiler.h)
+ * [root_type: byte] the root_type: MonoProfileGCRootType (profiler.h)
* [extra_info: uleb128] the extra_info value
* object, root_type and extra_info are repeated num_roots times
*
* type: TYPE_SAMPLE
* exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
* if exinfo == TYPE_SAMPLE_HIT
- * [sample_type: uleb128] type of sample (SAMPLE_*)
- * [timestamp: uleb128] nanoseconds since startup (note: different from other timestamps!)
- * if (format_version > 10)
- * [thread: sleb128] thread id as difference from ptr_base
+ * [sample_type: byte] type of sample (SAMPLE_*)
+ * [thread: sleb128] thread id as difference from ptr_base
* [count: uleb128] number of following instruction addresses
* [ip: sleb128]* instruction pointer as difference from ptr_base
- * if (format_version > 5)
- * [mbt_count: uleb128] number of managed backtrace info triplets (method + IL offset + native offset)
- * [method: sleb128]* MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
- * [il_offset: sleb128]* IL offset inside method where the hit occurred
- * [native_offset: sleb128]* native offset inside method where the hit occurred
+ * [mbt_count: uleb128] number of managed backtrace frames
+ * [method: sleb128]* MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
* if exinfo == TYPE_SAMPLE_USYM
* [address: sleb128] symbol address as a difference from ptr_base
* [size: uleb128] symbol size (may be 0 if unknown)
* [name: string] symbol name
* if exinfo == TYPE_SAMPLE_UBIN
- * [time diff: uleb128] nanoseconds since last timing
* [address: sleb128] address where binary has been loaded
* [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
* [size: uleb128] memory size
* if section == MONO_COUNTER_PERFCOUNTERS:
* [section_name: string] section name of counter
* [name: string] name of counter
- * [type: uleb128] type of counter
- * [unit: uleb128] unit of counter
- * [variance: uleb128] variance of counter
+ * [type: byte] type of counter
+ * [unit: byte] unit of counter
+ * [variance: byte] variance of counter
* [index: uleb128] unique index of counter
* if exinfo == TYPE_SAMPLE_COUNTERS
- * [timestamp: uleb128] sampling timestamp
* while true:
* [index: uleb128] unique index of counter
* if index == 0:
* break
- * [type: uleb128] type of counter value
+ * [type: byte] type of counter value
* if type == string:
* if value == null:
* [0: uleb128] 0 -> value is null
* [partially_covered: uleb128] the number of partially covered methods
* currently partially_covered will always be 0, and fully_covered is the
* number of methods that are fully and partially covered.
- */
-
-/*
- * Format oddities that we ought to fix:
- *
- * - Methods written in emit_bt () should be based on the buffer's base
- * method instead of the base pointer.
- * - The TYPE_SAMPLE_HIT event contains (currently) pointless data like
- * always-one unmanaged frame count and always-zero IL offsets.
*
- * These are mostly small things and are not worth a format change by
- * themselves. They should be done when some other major change has to
- * be done to the format.
+ * type meta format:
+ * type: TYPE_META
+ * exinfo: one of: TYPE_SYNC_POINT
+ * if exinfo == TYPE_SYNC_POINT
+ * [type: byte] MonoProfilerSyncPointType enum value
*/
// Pending data to be written to the log, for a single thread.
// Threads periodically flush their own LogBuffers by calling safe_send
+typedef struct _LogBuffer LogBuffer;
struct _LogBuffer {
// Next (older) LogBuffer in processing queue
LogBuffer *next;
uintptr_t last_method;
uintptr_t obj_base;
uintptr_t thread_id;
- int locked;
- int call_depth;
// Bytes allocated for this LogBuffer
int size;
unsigned char buf [1];
};
+typedef struct {
+ MonoLinkedListSetNode node;
+
+ // The current log buffer for this thread.
+ LogBuffer *buffer;
+
+ // Methods referenced by events in `buffer`, see `MethodInfo`.
+ GPtrArray *methods;
+
+ // Current call depth for enter/leave events.
+ int call_depth;
+
+ // Indicates whether this thread is currently writing to its `buffer`.
+ int busy;
+} MonoProfilerThread;
+
static inline void
ign_res (int G_GNUC_UNUSED unused, ...)
{
}
-#define ENTER_LOG(lb,str) if ((lb)->locked) {ign_res (write(2, str, strlen(str))); ign_res (write(2, "\n", 1));return;} else {(lb)->locked++;}
-#define EXIT_LOG(lb) (lb)->locked--;
+/*
+ * These macros create a scope to avoid leaking the buffer returned
+ * from ensure_logbuf () as it may have been invalidated by a GC
+ * thread during STW. If you called init_thread () with add_to_lls =
+ * FALSE, then don't use these macros.
+ */
-typedef struct _BinaryObject BinaryObject;
+#define ENTER_LOG \
+ do { \
+ buffer_lock (); \
+ g_assert (!PROF_TLS_GET ()->busy++ && "Why are we trying to write a new event while already writing one?")
+
+#define EXIT_LOG \
+ PROF_TLS_GET ()->busy--; \
+ buffer_unlock (); \
+ } while (0)
+
+static volatile gint32 buffer_rwlock_count;
+static volatile gpointer buffer_rwlock_exclusive;
+
+// Can be used recursively.
+static void
+buffer_lock (void)
+{
+ /*
+ * If the thread holding the exclusive lock tries to modify the
+ * reader count, just make it a no-op. This way, we also avoid
+ * invoking the GC safe point macros below, which could break if
+ * done from a thread that is currently the initiator of STW.
+ *
+ * In other words, we rely on the fact that the GC thread takes
+ * the exclusive lock in the gc_event () callback when the world
+ * is about to stop.
+ */
+ if (InterlockedReadPointer (&buffer_rwlock_exclusive) != (gpointer) thread_id ()) {
+ MONO_ENTER_GC_SAFE;
+ while (InterlockedReadPointer (&buffer_rwlock_exclusive))
+ mono_thread_info_yield ();
+
+ InterlockedIncrement (&buffer_rwlock_count);
+
+ MONO_EXIT_GC_SAFE;
+ }
+
+ mono_memory_barrier ();
+}
+
+static void
+buffer_unlock (void)
+{
+ mono_memory_barrier ();
+
+ // See the comment in buffer_lock ().
+ if (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id ())
+ return;
+
+ g_assert (InterlockedRead (&buffer_rwlock_count) && "Why are we trying to decrement a zero reader count?");
+
+ InterlockedDecrement (&buffer_rwlock_count);
+}
+
+// Cannot be used recursively.
+static void
+buffer_lock_excl (void)
+{
+ gpointer tid = (gpointer) thread_id ();
+
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) != tid && "Why are we taking the exclusive lock twice?");
+
+ MONO_ENTER_GC_SAFE;
+
+ while (InterlockedCompareExchangePointer (&buffer_rwlock_exclusive, tid, 0))
+ mono_thread_info_yield ();
+
+ while (InterlockedRead (&buffer_rwlock_count))
+ mono_thread_info_yield ();
+
+ MONO_EXIT_GC_SAFE;
+
+ mono_memory_barrier ();
+}
+
+static void
+buffer_unlock_excl (void)
+{
+ mono_memory_barrier ();
+
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why is the exclusive lock not held?");
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why does another thread hold the exclusive lock?");
+ g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why are there readers when the exclusive lock is held?");
+
+ InterlockedWritePointer (&buffer_rwlock_exclusive, NULL);
+}
+
+typedef struct _BinaryObject BinaryObject;
struct _BinaryObject {
BinaryObject *next;
void *addr;
#if defined (HAVE_SYS_ZLIB)
gzFile gzfile;
#endif
+ char *args;
uint64_t startup_time;
int pipe_output;
int last_gc_gen_started;
pthread_t dumper_thread;
#endif
volatile gint32 run_writer_thread;
+ MonoLockFreeAllocSizeClass writer_entry_size_class;
+ MonoLockFreeAllocator writer_entry_allocator;
MonoLockFreeQueue writer_queue;
MonoSemType writer_queue_sem;
MonoConcurrentHashTable *method_table;
GPtrArray *coverage_filters;
};
-typedef struct _WriterQueueEntry WriterQueueEntry;
-struct _WriterQueueEntry {
+typedef struct {
MonoLockFreeQueueNode node;
GPtrArray *methods;
LogBuffer *buffer;
-};
+} WriterQueueEntry;
-typedef struct _MethodInfo MethodInfo;
-struct _MethodInfo {
+#define WRITER_ENTRY_BLOCK_SIZE (mono_pagesize ())
+
+typedef struct {
MonoMethod *method;
MonoJitInfo *ji;
uint64_t time;
-};
-
-#ifdef TLS_INIT
-#undef TLS_INIT
-#endif
+} MethodInfo;
#ifdef HOST_WIN32
-#define TLS_SET(x,y) (TlsSetValue (x, y))
-#define TLS_GET(t,x) ((t *) TlsGetValue (x))
-#define TLS_INIT(x) (x = TlsAlloc ())
-static int tlsbuffer;
-static int tlsmethodlist;
+
+#define PROF_TLS_SET(VAL) (TlsSetValue (profiler_tls, (VAL)))
+#define PROF_TLS_GET() ((MonoProfilerThread *) TlsGetValue (profiler_tls))
+#define PROF_TLS_INIT() (profiler_tls = TlsAlloc ())
+#define PROF_TLS_FREE() (TlsFree (profiler_tls))
+
+static DWORD profiler_tls;
+
#elif HAVE_KW_THREAD
-#define TLS_SET(x,y) (x = y)
-#define TLS_GET(t,x) (x)
-#define TLS_INIT(x)
-static __thread LogBuffer* tlsbuffer = NULL;
-static __thread GPtrArray* tlsmethodlist = NULL;
+
+#define PROF_TLS_SET(VAL) (profiler_tls = (VAL))
+#define PROF_TLS_GET() (profiler_tls)
+#define PROF_TLS_INIT()
+#define PROF_TLS_FREE()
+
+static __thread MonoProfilerThread *profiler_tls;
+
#else
-#define TLS_SET(x,y) (pthread_setspecific (x, y))
-#define TLS_GET(t,x) ((t *) pthread_getspecific (x))
-#define TLS_INIT(x) (pthread_key_create (&x, NULL))
-static pthread_key_t tlsbuffer;
-static pthread_key_t tlsmethodlist;
-#endif
-static void safe_send (MonoProfiler *profiler, LogBuffer *logbuffer);
+#define PROF_TLS_SET(VAL) (pthread_setspecific (profiler_tls, (VAL)))
+#define PROF_TLS_GET() ((MonoProfilerThread *) pthread_getspecific (profiler_tls))
+#define PROF_TLS_INIT() (pthread_key_create (&profiler_tls, NULL))
+#define PROF_TLS_FREE() (pthread_key_delete (&profiler_tls))
+
+static pthread_key_t profiler_tls;
+
+#endif
static char*
pstrdup (const char *s)
}
static void
-init_thread (void)
+init_buffer_state (MonoProfilerThread *thread)
{
- if (!TLS_GET (LogBuffer, tlsbuffer)) {
- LogBuffer *logbuffer = create_buffer ();
- TLS_SET (tlsbuffer, logbuffer);
- logbuffer->thread_id = thread_id ();
- }
- if (!TLS_GET (GPtrArray, tlsmethodlist)) {
- GPtrArray *methodlist = g_ptr_array_new ();
- TLS_SET (tlsmethodlist, methodlist);
+ thread->buffer = create_buffer ();
+ thread->methods = NULL;
+}
+
+static void
+clear_hazard_pointers (MonoThreadHazardPointers *hp)
+{
+ mono_hazard_pointer_clear (hp, 0);
+ mono_hazard_pointer_clear (hp, 1);
+ mono_hazard_pointer_clear (hp, 2);
+}
+
+static MonoProfilerThread *
+init_thread (gboolean add_to_lls)
+{
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+
+ /*
+ * Sometimes we may try to initialize a thread twice. One example is the
+ * main thread: We initialize it when setting up the profiler, but we will
+ * also get a thread_start () callback for it. Another example is when
+ * attaching new threads to the runtime: We may get a gc_alloc () callback
+ * for that thread's thread object (where we initialize it), soon followed
+ * by a thread_start () callback.
+ *
+ * These cases are harmless anyhow. Just return if we've already done the
+ * initialization work.
+ */
+ if (thread)
+ return thread;
+
+ thread = malloc (sizeof (MonoProfilerThread));
+ thread->node.key = thread_id ();
+ thread->call_depth = 0;
+ thread->busy = 0;
+
+ init_buffer_state (thread);
+
+ /*
+ * Some internal profiler threads don't need to be cleaned up
+ * by the main thread on shutdown.
+ */
+ if (add_to_lls) {
+ MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+ g_assert (mono_lls_insert (&profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
+ clear_hazard_pointers (hp);
}
- //printf ("thread %p at time %llu\n", (void*)logbuffer->thread_id, logbuffer->time_base);
+ PROF_TLS_SET (thread);
+
+ return thread;
+}
+
+// Only valid if init_thread () was called with add_to_lls = FALSE.
+static void
+deinit_thread (MonoProfilerThread *thread)
+{
+ free (thread);
+ PROF_TLS_SET (NULL);
}
static LogBuffer *
if (old && old->cursor + bytes + 100 < old->buf_end)
return old;
- LogBuffer *new_ = (LogBuffer *)create_buffer ();
- new_->thread_id = thread_id ();
+ LogBuffer *new_ = create_buffer ();
new_->next = old;
- if (old)
- new_->call_depth = old->call_depth;
-
return new_;
}
-static LogBuffer*
-ensure_logbuf (int bytes)
+// Only valid if init_thread () was called with add_to_lls = FALSE.
+static LogBuffer *
+ensure_logbuf_unsafe (int bytes)
{
- LogBuffer *old = TLS_GET (LogBuffer, tlsbuffer);
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+ LogBuffer *old = thread->buffer;
LogBuffer *new_ = ensure_logbuf_inner (old, bytes);
if (new_ == old)
return old; // Still enough space.
- TLS_SET (tlsbuffer, new_);
- init_thread ();
+ thread->buffer = new_;
return new_;
}
+/*
+ * Any calls to this function should be wrapped in the ENTER_LOG and
+ * EXIT_LOG macros to prevent the returned pointer from leaking
+ * outside of the critical region created by the calls to buffer_lock ()
+ * and buffer_unlock () that those macros insert. If the pointer leaks,
+ * it can and will lead to crashes as the GC or helper thread may
+ * invalidate the pointer at any time.
+ *
+ * Note: If you're calling from a thread that called init_thread () with
+ * add_to_lls = FALSE, you should use ensure_logbuf_unsafe () and omit
+ * the macros.
+ */
+static LogBuffer*
+ensure_logbuf (int bytes)
+{
+ g_assert (PROF_TLS_GET ()->busy && "Why are we trying to expand our buffer without the busy flag set?");
+
+ return ensure_logbuf_unsafe (bytes);
+}
+
static void
emit_byte (LogBuffer *logbuffer, int value)
{
assert (logbuffer->cursor <= logbuffer->buf_end);
}
+static void
+emit_event_time (LogBuffer *logbuffer, int event, uint64_t time)
+{
+ emit_byte (logbuffer, event);
+ emit_time (logbuffer, time);
+}
+
+static void
+emit_event (LogBuffer *logbuffer, int event)
+{
+ emit_event_time (logbuffer, event, current_time ());
+}
+
static void
emit_svalue (LogBuffer *logbuffer, int64_t value)
{
*/
//g_assert (ji);
- MethodInfo *info = (MethodInfo *)malloc (sizeof (MethodInfo));
+ MethodInfo *info = (MethodInfo *) malloc (sizeof (MethodInfo));
info->method = method;
info->ji = ji;
info->time = current_time ();
- g_ptr_array_add (TLS_GET (GPtrArray, tlsmethodlist), info);
+ MonoProfilerThread *thread = PROF_TLS_GET ();
+ GPtrArray *arr = thread->methods ? thread->methods : (thread->methods = g_ptr_array_new ());
+ g_ptr_array_add (arr, info);
}
}
emit_method_inner (logbuffer, method);
}
-static void
-emit_method_as_ptr (MonoProfiler *prof, LogBuffer *logbuffer, MonoMethod *method)
-{
- register_method_local (prof, method, NULL);
- emit_ptr (logbuffer, method);
-}
-
static void
emit_obj (LogBuffer *logbuffer, void *ptr)
{
return buf + 8;
}
+static char *
+write_header_string (char *p, const char *str)
+{
+ size_t len = strlen (str) + 1;
+
+ p = write_int32 (p, len);
+ strcpy (p, str);
+
+ return p + len;
+}
+
static void
dump_header (MonoProfiler *profiler)
{
- char hbuf [128];
+ const char *args = profiler->args;
+ const char *arch = mono_config_get_cpu ();
+ const char *os = mono_config_get_os ();
+
+ char *hbuf = malloc (
+ sizeof (gint32) /* header id */ +
+ sizeof (gint8) /* major version */ +
+ sizeof (gint8) /* minor version */ +
+ sizeof (gint8) /* data version */ +
+ sizeof (gint8) /* word size */ +
+ sizeof (gint64) /* startup time */ +
+ sizeof (gint32) /* timer overhead */ +
+ sizeof (gint32) /* flags */ +
+ sizeof (gint32) /* process id */ +
+ sizeof (gint16) /* command port */ +
+ sizeof (gint32) + strlen (args) + 1 /* arguments */ +
+ sizeof (gint32) + strlen (arch) + 1 /* architecture */ +
+ sizeof (gint32) + strlen (os) + 1 /* operating system */
+ );
char *p = hbuf;
+
p = write_int32 (p, LOG_HEADER_ID);
*p++ = LOG_VERSION_MAJOR;
*p++ = LOG_VERSION_MINOR;
*p++ = LOG_DATA_VERSION;
- *p++ = sizeof (void*);
- p = write_int64 (p, ((uint64_t)time (NULL)) * 1000); /* startup time */
- p = write_int32 (p, get_timer_overhead ()); /* timer overhead */
+ *p++ = sizeof (void *);
+ p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
+ p = write_int32 (p, get_timer_overhead ());
p = write_int32 (p, 0); /* flags */
- p = write_int32 (p, process_id ()); /* pid */
- p = write_int16 (p, profiler->command_port); /* port */
- p = write_int16 (p, 0); /* opsystem */
+ p = write_int32 (p, process_id ());
+ p = write_int16 (p, profiler->command_port);
+ p = write_header_string (p, args);
+ p = write_header_string (p, arch);
+ p = write_header_string (p, os);
+
#if defined (HAVE_SYS_ZLIB)
if (profiler->gzfile) {
gzwrite (profiler->gzfile, hbuf, p - hbuf);
- } else {
+ } else
+#endif
+ {
fwrite (hbuf, p - hbuf, 1, profiler->file);
+ fflush (profiler->file);
}
-#else
- fwrite (hbuf, p - hbuf, 1, profiler->file);
- fflush (profiler->file);
-#endif
+
+ free (hbuf);
}
static void
-send_buffer (MonoProfiler *prof, GPtrArray *methods, LogBuffer *buffer)
+send_buffer (MonoProfiler *prof, MonoProfilerThread *thread)
{
- WriterQueueEntry *entry = (WriterQueueEntry *)calloc (1, sizeof (WriterQueueEntry));
+ WriterQueueEntry *entry = mono_lock_free_alloc (&prof->writer_entry_allocator);
+ entry->methods = thread->methods;
+ entry->buffer = thread->buffer;
+
mono_lock_free_queue_node_init (&entry->node, FALSE);
- entry->methods = methods;
- entry->buffer = buffer;
+
mono_lock_free_queue_enqueue (&prof->writer_queue, &entry->node);
mono_os_sem_post (&prof->writer_queue_sem);
}
+static void
+remove_thread (MonoProfiler *prof, MonoProfilerThread *thread, gboolean from_callback)
+{
+ MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+
+ if (mono_lls_remove (&profiler_thread_list, hp, &thread->node)) {
+ LogBuffer *buffer = thread->buffer;
+
+ /*
+ * No need to take the buffer lock here as no other threads can
+ * be accessing this buffer anymore.
+ */
+
+ if (!from_callback) {
+ /*
+ * The thread is being cleaned up by the main thread during
+ * shutdown. This typically happens for internal runtime
+ * threads. We need to synthesize a thread end event.
+ */
+
+ buffer = ensure_logbuf_inner (buffer,
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
+ );
+
+ emit_event (buffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (buffer, TYPE_THREAD);
+ emit_ptr (buffer, (void *) thread->node.key);
+ }
+
+ send_buffer (prof, thread);
+
+ mono_thread_hazardous_try_free (thread, free);
+ }
+
+ clear_hazard_pointers (hp);
+
+ if (from_callback)
+ PROF_TLS_SET (NULL);
+}
+
static void
dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
{
char hbuf [128];
char *p = hbuf;
+
if (buf->next)
dump_buffer (profiler, buf->next);
+
p = write_int32 (p, BUF_ID);
p = write_int32 (p, buf->cursor - buf->buf);
p = write_int64 (p, buf->time_base);
p = write_int64 (p, buf->obj_base);
p = write_int64 (p, buf->thread_id);
p = write_int64 (p, buf->method_base);
+
#if defined (HAVE_SYS_ZLIB)
if (profiler->gzfile) {
gzwrite (profiler->gzfile, hbuf, p - hbuf);
gzwrite (profiler->gzfile, buf->buf, buf->cursor - buf->buf);
- } else {
+ } else
#endif
+ {
fwrite (hbuf, p - hbuf, 1, profiler->file);
fwrite (buf->buf, buf->cursor - buf->buf, 1, profiler->file);
fflush (profiler->file);
-#if defined (HAVE_SYS_ZLIB)
}
-#endif
+
free_buffer (buf, buf->size);
}
+static void
+dump_buffer_threadless (MonoProfiler *profiler, LogBuffer *buf)
+{
+ for (LogBuffer *iter = buf; iter; iter = iter->next)
+ iter->thread_id = 0;
+
+ dump_buffer (profiler, buf);
+}
+
static void
process_requests (MonoProfiler *profiler)
{
}
static void counters_init (MonoProfiler *profiler);
-static void counters_sample (MonoProfiler *profiler, uint64_t timestamp, gboolean threadless);
+static void counters_sample (MonoProfiler *profiler, uint64_t timestamp);
-/*
- * Can be called only at safe callback locations.
- */
static void
-safe_send (MonoProfiler *profiler, LogBuffer *logbuffer)
+safe_send (MonoProfiler *profiler)
{
/* We need the runtime initialized so that we have threads and hazard
* pointers available. Otherwise, the lock free queue will not work and
if (!InterlockedRead (&runtime_inited))
return;
- int cd = logbuffer->call_depth;
+ MonoProfilerThread *thread = PROF_TLS_GET ();
- send_buffer (profiler, TLS_GET (GPtrArray, tlsmethodlist), TLS_GET (LogBuffer, tlsbuffer));
+ buffer_lock ();
- TLS_SET (tlsbuffer, NULL);
- TLS_SET (tlsmethodlist, NULL);
+ send_buffer (profiler, thread);
+ init_buffer_state (thread);
- init_thread ();
+ buffer_unlock ();
+}
- TLS_GET (LogBuffer, tlsbuffer)->call_depth = cd;
+static void
+send_if_needed (MonoProfiler *prof)
+{
+ if (PROF_TLS_GET ()->buffer->next)
+ safe_send (prof);
}
static void
-safe_send_threadless (MonoProfiler *prof, LogBuffer *buf)
+safe_send_threadless (MonoProfiler *prof)
{
+ LogBuffer *buf = PROF_TLS_GET ()->buffer;
+
for (LogBuffer *iter = buf; iter; iter = iter->next)
iter->thread_id = 0;
- safe_send (prof, buf);
+ safe_send (prof);
+}
+
+static void
+send_if_needed_threadless (MonoProfiler *prof)
+{
+ if (PROF_TLS_GET ()->buffer->next)
+ safe_send_threadless (prof);
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point_flush (MonoProfiler *prof)
+{
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
+
+ MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+ send_buffer (prof, thread);
+ init_buffer_state (thread);
+ } MONO_LLS_FOREACH_SAFE_END
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point_mark (MonoProfiler *prof, MonoProfilerSyncPointType type)
+{
+ g_assert (InterlockedReadPointer (&buffer_rwlock_exclusive) == (gpointer) thread_id () && "Why don't we hold the exclusive lock?");
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* type */
+ );
+
+ emit_event (logbuffer, TYPE_META | TYPE_SYNC_POINT);
+ emit_byte (logbuffer, type);
+
+ EXIT_LOG;
+
+ switch (type) {
+ case SYNC_POINT_PERIODIC:
+ safe_send_threadless (prof);
+ break;
+ case SYNC_POINT_WORLD_STOP:
+ case SYNC_POINT_WORLD_START:
+ safe_send (prof);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+// Assumes that the exclusive lock is held.
+static void
+sync_point (MonoProfiler *prof, MonoProfilerSyncPointType type)
+{
+ sync_point_flush (prof);
+ sync_point_mark (prof, type);
}
static int
gc_reference (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num, MonoObject **refs, uintptr_t *offsets, void *data)
{
- int i;
- uintptr_t last_offset = 0;
- //const char *name = mono_class_get_name (klass);
+ /* account for object alignment in the heap */
+ size += 7;
+ size &= ~7;
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
LEB128_SIZE /* obj */ +
LEB128_SIZE /* ref */
)
);
- emit_byte (logbuffer, TYPE_HEAP_OBJECT | TYPE_HEAP);
+
+ emit_event (logbuffer, TYPE_HEAP_OBJECT | TYPE_HEAP);
emit_obj (logbuffer, obj);
emit_ptr (logbuffer, klass);
- /* account for object alignment in the heap */
- size += 7;
- size &= ~7;
emit_value (logbuffer, size);
emit_value (logbuffer, num);
- for (i = 0; i < num; ++i) {
+
+ uintptr_t last_offset = 0;
+
+ for (int i = 0; i < num; ++i) {
emit_value (logbuffer, offsets [i] - last_offset);
last_offset = offsets [i];
emit_obj (logbuffer, refs [i]);
}
- //if (num)
- // printf ("obj: %p, klass: %s, refs: %d, size: %d\n", obj, name, (int)num, (int)size);
+
+ EXIT_LOG;
+
return 0;
}
static void
heap_walk (MonoProfiler *profiler)
{
- int do_walk = 0;
- uint64_t now;
- LogBuffer *logbuffer;
if (!do_heap_shot)
return;
- logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */
- );
- now = current_time ();
- if (hs_mode_ms && (now - last_hs_time)/1000000 >= hs_mode_ms)
- do_walk = 1;
+
+ gboolean do_walk = 0;
+ uint64_t now = current_time ();
+
+ if (hs_mode_ms && (now - last_hs_time) / 1000000 >= hs_mode_ms)
+ do_walk = TRUE;
else if (hs_mode_gc && (gc_count % hs_mode_gc) == 0)
- do_walk = 1;
+ do_walk = TRUE;
else if (hs_mode_ondemand)
do_walk = heapshot_requested;
else if (!hs_mode_ms && !hs_mode_gc && profiler->last_gc_gen_started == mono_gc_max_generation ())
- do_walk = 1;
+ do_walk = TRUE;
if (!do_walk)
return;
+
heapshot_requested = 0;
- emit_byte (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
- emit_time (logbuffer, now);
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
+
+ EXIT_LOG;
+
mono_gc_walk_heap (0, gc_reference, NULL);
- logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */
);
+
now = current_time ();
- emit_byte (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
+
+ EXIT_LOG;
+
last_hs_time = now;
}
static void
-gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation) {
- uint64_t now;
+gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
+{
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* gc event */ +
- LEB128_SIZE /* generation */
+ BYTE_SIZE /* gc event */ +
+ BYTE_SIZE /* generation */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "gcevent");
- emit_byte (logbuffer, TYPE_GC_EVENT | TYPE_GC);
- emit_time (logbuffer, now);
- emit_value (logbuffer, ev);
- emit_value (logbuffer, generation);
- /* to deal with nested gen1 after gen0 started */
- if (ev == MONO_GC_EVENT_START) {
+
+ emit_event (logbuffer, TYPE_GC_EVENT | TYPE_GC);
+ emit_byte (logbuffer, ev);
+ emit_byte (logbuffer, generation);
+
+ EXIT_LOG;
+
+ switch (ev) {
+ case MONO_GC_EVENT_START:
+ /* to deal with nested gen1 after gen0 started */
profiler->last_gc_gen_started = generation;
+
if (generation == mono_gc_max_generation ())
gc_count++;
- }
- if (ev == MONO_GC_EVENT_PRE_START_WORLD)
+ break;
+ case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
+ /*
+ * Ensure that no thread can be in the middle of writing to
+ * a buffer when the world stops...
+ */
+ buffer_lock_excl ();
+ break;
+ case MONO_GC_EVENT_POST_STOP_WORLD:
+ /*
+ * ... So that we now have a consistent view of all buffers.
+ * This allows us to flush them. We need to do this because
+ * they may contain object allocation events that need to be
+ * committed to the log file before any object move events
+ * that will be produced during this GC.
+ */
+ sync_point (profiler, SYNC_POINT_WORLD_STOP);
+ break;
+ case MONO_GC_EVENT_PRE_START_WORLD:
heap_walk (profiler);
- EXIT_LOG (logbuffer);
- if (ev == MONO_GC_EVENT_POST_START_WORLD)
- safe_send (profiler, logbuffer);
- //printf ("gc event %d for generation %d\n", ev, generation);
+ break;
+ case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
+ /*
+ * Similarly, we must now make sure that any object moves
+ * written to the GC thread's buffer are flushed. Otherwise,
+ * object allocation events for certain addresses could come
+ * after the move events that made those addresses available.
+ */
+ sync_point_mark (profiler, SYNC_POINT_WORLD_START);
+
+ /*
+ * Finally, it is safe to allow other threads to write to
+ * their buffers again.
+ */
+ buffer_unlock_excl ();
+ break;
+ default:
+ break;
+ }
}
static void
-gc_resize (MonoProfiler *profiler, int64_t new_size) {
- uint64_t now;
+gc_resize (MonoProfiler *profiler, int64_t new_size)
+{
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* new size */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "gcresize");
- emit_byte (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
emit_value (logbuffer, new_size);
- //printf ("gc resized to %lld\n", new_size);
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
}
// If you alter MAX_FRAMES, you may need to alter SAMPLE_BLOCK_SIZE too.
*/
if (data->count > num_frames)
printf ("bad num frames: %d\n", data->count);
- emit_value (logbuffer, 0); /* flags */
emit_value (logbuffer, data->count);
//if (*p != data.count) {
// printf ("bad num frames enc at %d: %d -> %d\n", count, data.count, *p); printf ("frames end: %p->%p\n", p, logbuffer->cursor); exit(0);}
while (data->count) {
- emit_method_as_ptr (prof, logbuffer, data->methods [--data->count]);
+ emit_method (prof, logbuffer, data->methods [--data->count]);
}
}
static void
gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
{
- uint64_t now;
- uintptr_t len;
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces)? TYPE_ALLOC_BT: 0;
+ init_thread (TRUE);
+
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_ALLOC_BT : 0;
FrameData data;
- LogBuffer *logbuffer;
- len = mono_object_get_size (obj);
+ uintptr_t len = mono_object_get_size (obj);
/* account for object alignment in the heap */
len += 7;
len &= ~7;
+
if (do_bt)
collect_bt (&data);
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* klass */ +
LEB128_SIZE /* obj */ +
LEB128_SIZE /* size */ +
(do_bt ? (
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* count */ +
data.count * (
LEB128_SIZE /* method */
)
) : 0)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "gcalloc");
- emit_byte (logbuffer, do_bt | TYPE_ALLOC);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, do_bt | TYPE_ALLOC);
emit_ptr (logbuffer, klass);
emit_obj (logbuffer, obj);
emit_value (logbuffer, len);
+
if (do_bt)
emit_bt (prof, logbuffer, &data);
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+
+ EXIT_LOG;
+
+ send_if_needed (prof);
+
process_requests (prof);
- //printf ("gc alloc %s at %p\n", mono_class_get_name (klass), obj);
}
static void
gc_moves (MonoProfiler *prof, void **objects, int num)
{
- int i;
- uint64_t now;
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* num */ +
num * (
LEB128_SIZE /* object */
)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "gcmove");
- emit_byte (logbuffer, TYPE_GC_MOVE | TYPE_GC);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_GC_MOVE | TYPE_GC);
emit_value (logbuffer, num);
- for (i = 0; i < num; ++i)
+
+ for (int i = 0; i < num; ++i)
emit_obj (logbuffer, objects [i]);
- //printf ("gc moved %d objects\n", num/2);
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
}
static void
gc_roots (MonoProfiler *prof, int num, void **objects, int *root_types, uintptr_t *extra_info)
{
- int i;
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
LEB128_SIZE /* num */ +
LEB128_SIZE /* extra info */
)
);
- ENTER_LOG (logbuffer, "gcroots");
- emit_byte (logbuffer, TYPE_HEAP_ROOT | TYPE_HEAP);
+
+ emit_event (logbuffer, TYPE_HEAP_ROOT | TYPE_HEAP);
emit_value (logbuffer, num);
emit_value (logbuffer, mono_gc_collection_count (mono_gc_max_generation ()));
- for (i = 0; i < num; ++i) {
+
+ for (int i = 0; i < num; ++i) {
emit_obj (logbuffer, objects [i]);
- emit_value (logbuffer, root_types [i]);
+ emit_byte (logbuffer, root_types [i]);
emit_value (logbuffer, extra_info [i]);
}
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
}
static void
gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj)
{
int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
- uint64_t now;
FrameData data;
if (do_bt)
collect_bt (&data);
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* type */ +
LEB128_SIZE /* handle */ +
(op == MONO_PROFILER_GC_HANDLE_CREATED ? (
LEB128_SIZE /* obj */
) : 0) +
(do_bt ? (
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* count */ +
data.count * (
LEB128_SIZE /* method */
) : 0)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "gchandle");
-
if (op == MONO_PROFILER_GC_HANDLE_CREATED)
- emit_byte (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
+ emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
- emit_byte (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
+ emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
else
g_assert_not_reached ();
- emit_time (logbuffer, now);
emit_value (logbuffer, type);
emit_value (logbuffer, handle);
if (do_bt)
emit_bt (prof, logbuffer, &data);
- EXIT_LOG (logbuffer);
+ EXIT_LOG;
+
+ process_requests (prof);
+}
+
+static void
+finalize_begin (MonoProfiler *prof)
+{
+ ENTER_LOG;
+
+ LogBuffer *buf = ensure_logbuf (
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_START | TYPE_GC);
+
+ EXIT_LOG;
+
+ process_requests (prof);
+}
+
+static void
+finalize_end (MonoProfiler *prof)
+{
+ ENTER_LOG;
+
+ LogBuffer *buf = ensure_logbuf (
+ EVENT_SIZE /* event */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_END | TYPE_GC);
+
+ EXIT_LOG;
+
+ process_requests (prof);
+}
+
+static void
+finalize_object_begin (MonoProfiler *prof, MonoObject *obj)
+{
+ ENTER_LOG;
+
+ LogBuffer *buf = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* obj */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_OBJECT_START | TYPE_GC);
+ emit_obj (buf, obj);
+
+ EXIT_LOG;
+
+ process_requests (prof);
+}
+
+static void
+finalize_object_end (MonoProfiler *prof, MonoObject *obj)
+{
+ ENTER_LOG;
+
+ LogBuffer *buf = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* obj */
+ );
+
+ emit_event (buf, TYPE_GC_FINALIZE_OBJECT_END | TYPE_GC);
+ emit_obj (buf, obj);
+
+ EXIT_LOG;
+
process_requests (prof);
}
static void
image_loaded (MonoProfiler *prof, MonoImage *image, int result)
{
- uint64_t now;
- const char *name;
- int nlen;
- LogBuffer *logbuffer;
if (result != MONO_PROFILE_OK)
return;
- name = mono_image_get_filename (image);
- nlen = strlen (name) + 1;
- logbuffer = ensure_logbuf (
+
+ const char *name = mono_image_get_filename (image);
+ int nlen = strlen (name) + 1;
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* image */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "image");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_IMAGE);
emit_ptr (logbuffer, image);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- //printf ("loaded image %p (%s)\n", image, name);
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+
+ EXIT_LOG;
+
+ send_if_needed (prof);
+
process_requests (prof);
InterlockedIncrement (&image_loads);
{
const char *name = mono_image_get_filename (image);
int nlen = strlen (name) + 1;
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* image */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "image-unload");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_IMAGE);
emit_ptr (logbuffer, image);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
int nlen = strlen (name) + 1;
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* assembly */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "assembly-load");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_ASSEMBLY);
emit_ptr (logbuffer, assembly);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
mono_free (name);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ send_if_needed (prof);
process_requests (prof);
{
char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
int nlen = strlen (name) + 1;
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* assembly */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "assembly-unload");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_ASSEMBLY);
emit_ptr (logbuffer, assembly);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
mono_free (name);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ send_if_needed (prof);
process_requests (prof);
static void
class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
{
- uint64_t now;
- char *name;
- int nlen;
- MonoImage *image;
- LogBuffer *logbuffer;
if (result != MONO_PROFILE_OK)
return;
+
+ char *name;
+
if (InterlockedRead (&runtime_inited))
name = mono_type_get_name (mono_class_get_type (klass));
else
name = type_name (klass);
- nlen = strlen (name) + 1;
- image = mono_class_get_image (klass);
- logbuffer = ensure_logbuf (
+
+ int nlen = strlen (name) + 1;
+ MonoImage *image = mono_class_get_image (klass);
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* klass */ +
LEB128_SIZE /* image */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "class");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_CLASS);
emit_ptr (logbuffer, klass);
emit_ptr (logbuffer, image);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- //printf ("loaded class %p (%s)\n", klass, name);
+
+ EXIT_LOG;
+
if (runtime_inited)
mono_free (name);
else
free (name);
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+
+ send_if_needed (prof);
+
process_requests (prof);
InterlockedIncrement (&class_loads);
int nlen = strlen (name) + 1;
MonoImage *image = mono_class_get_image (klass);
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* klass */ +
LEB128_SIZE /* image */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "class-unload");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_CLASS);
emit_ptr (logbuffer, klass);
emit_ptr (logbuffer, image);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
if (runtime_inited)
mono_free (name);
else
free (name);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ send_if_needed (prof);
process_requests (prof);
static void
method_enter (MonoProfiler *prof, MonoMethod *method)
{
- uint64_t now = current_time ();
+#ifndef DISABLE_HELPER_THREAD
+ process_method_enter_coverage (prof, method);
+#endif /* DISABLE_HELPER_THREAD */
+
+ if (PROF_TLS_GET ()->call_depth++ <= max_call_depth) {
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_ENTER | TYPE_METHOD);
+ emit_method (prof, logbuffer, method);
-#ifndef DISABLE_HELPER_THREAD
- process_method_enter_coverage (prof, method);
-#endif /* DISABLE_HELPER_THREAD */
+ EXIT_LOG;
+ }
- LogBuffer *logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* method */
- );
- if (logbuffer->call_depth++ > max_call_depth)
- return;
- ENTER_LOG (logbuffer, "enter");
- emit_byte (logbuffer, TYPE_ENTER | TYPE_METHOD);
- emit_time (logbuffer, now);
- emit_method (prof, logbuffer, method);
- EXIT_LOG (logbuffer);
+ send_if_needed (prof);
process_requests (prof);
}
static void
method_leave (MonoProfiler *prof, MonoMethod *method)
{
- uint64_t now;
- LogBuffer *logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* method */
- );
- if (--logbuffer->call_depth > max_call_depth)
- return;
- now = current_time ();
- ENTER_LOG (logbuffer, "leave");
- emit_byte (logbuffer, TYPE_LEAVE | TYPE_METHOD);
- emit_time (logbuffer, now);
- emit_method (prof, logbuffer, method);
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ if (--PROF_TLS_GET ()->call_depth <= max_call_depth) {
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_LEAVE | TYPE_METHOD);
+ emit_method (prof, logbuffer, method);
+
+ EXIT_LOG;
+ }
+
+ send_if_needed (prof);
+
process_requests (prof);
}
static void
method_exc_leave (MonoProfiler *prof, MonoMethod *method)
{
- uint64_t now;
- LogBuffer *logbuffer;
- if (nocalls)
- return;
- logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* method */
- );
- if (--logbuffer->call_depth > max_call_depth)
- return;
- now = current_time ();
- ENTER_LOG (logbuffer, "eleave");
- emit_byte (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
- emit_time (logbuffer, now);
- emit_method (prof, logbuffer, method);
- EXIT_LOG (logbuffer);
+ if (!nocalls && --PROF_TLS_GET ()->call_depth <= max_call_depth) {
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ LEB128_SIZE /* method */
+ );
+
+ emit_event (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
+ emit_method (prof, logbuffer, method);
+
+ EXIT_LOG;
+ }
+
+ send_if_needed (prof);
+
process_requests (prof);
}
static void
code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
{
- uint64_t now;
- int nlen;
char *name;
- LogBuffer *logbuffer;
+ int nlen;
+
if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
- name = (char *)data;
+ name = (char *) data;
nlen = strlen (name) + 1;
} else {
name = NULL;
nlen = 0;
}
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* buffer */ +
LEB128_SIZE /* size */ +
(name ? (
nlen /* name */
) : 0)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "code buffer");
- emit_byte (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
- emit_time (logbuffer, now);
- emit_value (logbuffer, type);
+
+ emit_event (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
+ emit_byte (logbuffer, type);
emit_ptr (logbuffer, buffer);
emit_value (logbuffer, size);
+
if (name) {
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
}
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
+
process_requests (prof);
}
static void
throw_exc (MonoProfiler *prof, MonoObject *object)
{
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces)? TYPE_EXCEPTION_BT: 0;
- uint64_t now;
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_THROW_BT : 0;
FrameData data;
- LogBuffer *logbuffer;
+
if (do_bt)
collect_bt (&data);
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* object */ +
(do_bt ? (
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* count */ +
data.count * (
LEB128_SIZE /* method */
)
) : 0)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "throw");
- emit_byte (logbuffer, do_bt | TYPE_EXCEPTION);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, do_bt | TYPE_EXCEPTION);
emit_obj (logbuffer, object);
+
if (do_bt)
emit_bt (prof, logbuffer, &data);
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
+
process_requests (prof);
}
static void
clause_exc (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num)
{
- uint64_t now;
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- LEB128_SIZE /* clause type */ +
+ BYTE_SIZE /* clause type */ +
LEB128_SIZE /* clause num */ +
LEB128_SIZE /* method */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "clause");
- emit_byte (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
- emit_time (logbuffer, now);
- emit_value (logbuffer, clause_type);
+
+ emit_event (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
+ emit_byte (logbuffer, clause_type);
emit_value (logbuffer, clause_num);
emit_method (prof, logbuffer, method);
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
process_requests (prof);
}
static void
monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent event)
{
- int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces && event == MONO_PROFILER_MONITOR_CONTENTION)? TYPE_MONITOR_BT: 0;
- uint64_t now;
+ int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces && event == MONO_PROFILER_MONITOR_CONTENTION) ? TYPE_MONITOR_BT : 0;
FrameData data;
- LogBuffer *logbuffer;
+
if (do_bt)
collect_bt (&data);
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* object */ +
(do_bt ? (
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* count */ +
data.count * (
LEB128_SIZE /* method */
)
) : 0)
);
- now = current_time ();
- ENTER_LOG (logbuffer, "monitor");
- emit_byte (logbuffer, (event << 4) | do_bt | TYPE_MONITOR);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, (event << 4) | do_bt | TYPE_MONITOR);
emit_obj (logbuffer, object);
+
if (do_bt)
emit_bt (profiler, logbuffer, &data);
- EXIT_LOG (logbuffer);
+
+ EXIT_LOG;
+
process_requests (profiler);
}
static void
thread_start (MonoProfiler *prof, uintptr_t tid)
{
- //printf ("thread start %p\n", (void*)tid);
- init_thread ();
+ init_thread (TRUE);
+
+ ENTER_LOG;
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
- LEB128_SIZE /* tid */ +
- LEB128_SIZE /* flags */
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "thread-start");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_THREAD);
emit_ptr (logbuffer, (void*) tid);
- emit_value (logbuffer, 0); /* flags */
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
static void
thread_end (MonoProfiler *prof, uintptr_t tid)
{
- if (TLS_GET (LogBuffer, tlsbuffer)) {
- LogBuffer *logbuffer = ensure_logbuf (
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
- LEB128_SIZE /* tid */ +
- LEB128_SIZE /* flags */
- );
- uint64_t now = current_time ();
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
+ EVENT_SIZE /* event */ +
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* tid */
+ );
- ENTER_LOG (logbuffer, "thread-end");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
- emit_byte (logbuffer, TYPE_THREAD);
- emit_ptr (logbuffer, (void*) tid);
- emit_value (logbuffer, 0); /* flags */
- EXIT_LOG (logbuffer);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+ emit_byte (logbuffer, TYPE_THREAD);
+ emit_ptr (logbuffer, (void*) tid);
- send_buffer (prof, TLS_GET (GPtrArray, tlsmethodlist), logbuffer);
+ EXIT_LOG;
- /* Don't process requests as the thread is detached from the runtime. */
- }
+ // Don't process requests as the thread is detached from the runtime.
- TLS_SET (tlsbuffer, NULL);
- TLS_SET (tlsmethodlist, NULL);
+ remove_thread (prof, PROF_TLS_GET (), TRUE);
InterlockedIncrement (&thread_ends);
}
if (result != MONO_PROFILE_OK)
return;
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
- LEB128_SIZE /* domain id */ +
- LEB128_SIZE /* flags */
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* domain id */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "domain-start");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_DOMAIN);
emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
- emit_value (logbuffer, 0); /* flags */
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
static void
domain_unloaded (MonoProfiler *prof, MonoDomain *domain)
{
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
- LEB128_SIZE /* domain id */ +
- LEB128_SIZE /* flags */
+ BYTE_SIZE /* type */ +
+ LEB128_SIZE /* domain id */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "domain-end");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_DOMAIN);
emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
- emit_value (logbuffer, 0); /* flags */
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
domain_name (MonoProfiler *prof, MonoDomain *domain, const char *name)
{
int nlen = strlen (name) + 1;
+
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* domain id */ +
- LEB128_SIZE /* flags */ +
nlen /* name */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "domain-name");
- emit_byte (logbuffer, TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_METADATA);
emit_byte (logbuffer, TYPE_DOMAIN);
emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, nlen);
logbuffer->cursor += nlen;
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
}
static void
context_loaded (MonoProfiler *prof, MonoAppContext *context)
{
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* context id */ +
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* domain id */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "context-start");
- emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_CONTEXT);
emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
- emit_value (logbuffer, 0); /* flags */
emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
static void
context_unloaded (MonoProfiler *prof, MonoAppContext *context)
{
+ ENTER_LOG;
+
LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* context id */ +
- LEB128_SIZE /* flags */ +
LEB128_SIZE /* domain id */
);
- uint64_t now = current_time ();
- ENTER_LOG (logbuffer, "context-end");
- emit_byte (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_time (logbuffer, now);
+ emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
emit_byte (logbuffer, TYPE_CONTEXT);
emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
- emit_value (logbuffer, 0); /* flags */
emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
{
int len = strlen (name) + 1;
- uint64_t now;
- LogBuffer *logbuffer;
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
- EVENT_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* tid */ +
- LEB128_SIZE /* flags */ +
len /* name */
);
- now = current_time ();
- ENTER_LOG (logbuffer, "tname");
- emit_byte (logbuffer, TYPE_METADATA);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_METADATA);
emit_byte (logbuffer, TYPE_THREAD);
emit_ptr (logbuffer, (void*)tid);
- emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->cursor, name, len);
logbuffer->cursor += len;
- EXIT_LOG (logbuffer);
- if (logbuffer->next)
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
process_requests (prof);
}
typedef struct {
MonoLockFreeQueueNode node;
MonoProfiler *prof;
- uint64_t elapsed;
+ uint64_t time;
uintptr_t tid;
void *ip;
int count;
InterlockedIncrement (&sample_hits);
- uint64_t now = current_time ();
-
SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
if (!sample) {
sample->count = 0;
mono_stack_walk_async_safe (&async_walk_stack, context, sample);
- uintptr_t elapsed = (now - profiler->startup_time) / 10000;
-
- sample->elapsed = elapsed;
+ sample->time = current_time ();
sample->tid = thread_id ();
sample->ip = ip;
if (do_debug) {
int len;
char buf [256];
- snprintf (buf, sizeof (buf), "hit at %p in thread %p after %llu ms\n", ip, (void *) thread_id (), (unsigned long long int) elapsed / 100);
+ snprintf (buf, sizeof (buf), "hit at %p in thread %p after %llu ms\n", ip, (void *) sample->tid, (unsigned long long int) ((sample->time - profiler->startup_time) / 10000 / 100));
len = strlen (buf);
ign_res (write (2, buf, len));
}
static void
dump_ubin (const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
{
- uint64_t now;
- LogBuffer *logbuffer;
- int len;
- len = strlen (filename) + 1;
- now = current_time ();
- logbuffer = ensure_logbuf (
+ int len = strlen (filename) + 1;
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* load address */ +
LEB128_SIZE /* offset */ +
LEB128_SIZE /* size */ +
nlen /* file name */
);
- emit_byte (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
- emit_time (logbuffer, now);
+
+ emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
emit_svalue (logbuffer, load_addr);
emit_uvalue (logbuffer, offset);
emit_uvalue (logbuffer, size);
memcpy (logbuffer->cursor, filename, len);
logbuffer->cursor += len;
+
+ EXIT_LOG;
}
#endif
static void
dump_usym (const char *name, uintptr_t value, uintptr_t size)
{
- LogBuffer *logbuffer;
- int len;
- len = strlen (name) + 1;
- logbuffer = ensure_logbuf (
+ int len = strlen (name) + 1;
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
LEB128_SIZE /* value */ +
LEB128_SIZE /* size */ +
len /* name */
);
- emit_byte (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
+
+ emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
emit_ptr (logbuffer, (void*)value);
emit_value (logbuffer, size);
memcpy (logbuffer->cursor, name, len);
logbuffer->cursor += len;
+
+ EXIT_LOG;
}
/* ELF code crashes on some systems. */
static void
dump_perf_hits (MonoProfiler *prof, void *buf, int size)
{
- LogBuffer *logbuffer;
int count = 1;
int mbt_count = 0;
void *end = (char*)buf + size;
/*ip = (void*)s->ip;
printf ("sample: %d, size: %d, ip: %p (%s), timestamp: %llu, nframes: %llu\n",
s->h.type, s->h.size, ip, symbol_for (ip), s->timestamp, s->nframes);*/
- logbuffer = ensure_logbuf (
+
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* type */ +
- LEB128_SIZE /* time */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* tid */ +
LEB128_SIZE /* count */ +
count * (
) +
LEB128_SIZE /* managed count */ +
mbt_count * (
- LEB128_SIZE /* method */ +
- LEB128_SIZE /* il offset */ +
- LEB128_SIZE /* native offset */
+ LEB128_SIZE /* method */
)
);
- emit_byte (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT);
- emit_value (logbuffer, sample_type);
- emit_uvalue (logbuffer, s->timestamp - prof->startup_time);
+
+ emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT);
+ emit_byte (logbuffer, sample_type);
/*
* No useful thread ID to write here, since throughout the
* profiler we use pthread_self () but the ID we get from
emit_ptr (logbuffer, 0);
emit_value (logbuffer, count);
emit_ptr (logbuffer, (void*)(uintptr_t)s->ip);
- add_code_pointer (s->ip);
/* no support here yet for the managed backtrace */
emit_uvalue (logbuffer, mbt_count);
+
+ EXIT_LOG;
+
+ add_code_pointer (s->ip);
buf = (char*)buf + s->h.size;
samples++;
}
}
static void
-counters_emit (MonoProfiler *profiler, gboolean threadless)
+counters_emit (MonoProfiler *profiler)
{
MonoCounterAgent *agent;
- LogBuffer *logbuffer;
int len = 0;
int size =
EVENT_SIZE /* event */ +
size +=
LEB128_SIZE /* section */ +
strlen (mono_counter_get_name (agent->counter)) + 1 /* name */ +
- LEB128_SIZE /* type */ +
- LEB128_SIZE /* unit */ +
- LEB128_SIZE /* variance */ +
+ BYTE_SIZE /* type */ +
+ BYTE_SIZE /* unit */ +
+ BYTE_SIZE /* variance */ +
LEB128_SIZE /* index */
;
return;
}
- logbuffer = ensure_logbuf (size);
+ ENTER_LOG;
- ENTER_LOG (logbuffer, "counters");
- emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
+ LogBuffer *logbuffer = ensure_logbuf (size);
+
+ emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
emit_value (logbuffer, len);
+
for (agent = counters; agent; agent = agent->next) {
const char *name;
name = mono_counter_get_name (agent->counter);
emit_value (logbuffer, mono_counter_get_section (agent->counter));
emit_string (logbuffer, name, strlen (name) + 1);
- emit_value (logbuffer, mono_counter_get_type (agent->counter));
- emit_value (logbuffer, mono_counter_get_unit (agent->counter));
- emit_value (logbuffer, mono_counter_get_variance (agent->counter));
+ emit_byte (logbuffer, mono_counter_get_type (agent->counter));
+ emit_byte (logbuffer, mono_counter_get_unit (agent->counter));
+ emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
emit_value (logbuffer, agent->index);
agent->emitted = 1;
}
- EXIT_LOG (logbuffer);
- if (threadless)
- safe_send_threadless (profiler, logbuffer);
- else
- safe_send (profiler, logbuffer);
+ EXIT_LOG;
mono_os_mutex_unlock (&counters_mutex);
}
static void
-counters_sample (MonoProfiler *profiler, uint64_t timestamp, gboolean threadless)
+counters_sample (MonoProfiler *profiler, uint64_t timestamp)
{
MonoCounterAgent *agent;
MonoCounter *counter;
- LogBuffer *logbuffer;
int type;
int buffer_size;
void *buffer;
if (!counters_initialized)
return;
- counters_emit (profiler, threadless);
+ counters_emit (profiler);
buffer_size = 8;
buffer = calloc (1, buffer_size);
mono_os_mutex_lock (&counters_mutex);
size =
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */
+ EVENT_SIZE /* event */
;
for (agent = counters; agent; agent = agent->next) {
size +=
LEB128_SIZE /* index */ +
- LEB128_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
mono_counter_get_size (agent->counter) /* value */
;
}
LEB128_SIZE /* stop marker */
;
- logbuffer = ensure_logbuf (size);
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (size);
+
+ emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
- ENTER_LOG (logbuffer, "counters");
- emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE);
- emit_uvalue (logbuffer, timestamp);
for (agent = counters; agent; agent = agent->next) {
size_t size;
}
emit_uvalue (logbuffer, agent->index);
- emit_uvalue (logbuffer, type);
+ emit_byte (logbuffer, type);
switch (type) {
case MONO_COUNTER_INT:
#if SIZEOF_VOID_P == 4
free (buffer);
emit_value (logbuffer, 0);
- EXIT_LOG (logbuffer);
- if (threadless)
- safe_send_threadless (profiler, logbuffer);
- else
- safe_send (profiler, logbuffer);
+ EXIT_LOG;
mono_os_mutex_unlock (&counters_mutex);
}
static PerfCounterAgent *perfcounters = NULL;
static void
-perfcounters_emit (MonoProfiler *profiler, gboolean threadless)
+perfcounters_emit (MonoProfiler *profiler)
{
PerfCounterAgent *pcagent;
- LogBuffer *logbuffer;
int len = 0;
int size =
EVENT_SIZE /* event */ +
LEB128_SIZE /* section */ +
strlen (pcagent->category_name) + 1 /* category name */ +
strlen (pcagent->name) + 1 /* name */ +
- LEB128_SIZE /* type */ +
- LEB128_SIZE /* unit */ +
- LEB128_SIZE /* variance */ +
+ BYTE_SIZE /* type */ +
+ BYTE_SIZE /* unit */ +
+ BYTE_SIZE /* variance */ +
LEB128_SIZE /* index */
;
if (!len)
return;
- logbuffer = ensure_logbuf (size);
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (size);
- ENTER_LOG (logbuffer, "perfcounters");
- emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
+ emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
emit_value (logbuffer, len);
+
for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
if (pcagent->emitted)
continue;
emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
- emit_value (logbuffer, MONO_COUNTER_LONG);
- emit_value (logbuffer, MONO_COUNTER_RAW);
- emit_value (logbuffer, MONO_COUNTER_VARIABLE);
+ emit_byte (logbuffer, MONO_COUNTER_LONG);
+ emit_byte (logbuffer, MONO_COUNTER_RAW);
+ emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
emit_value (logbuffer, pcagent->index);
pcagent->emitted = 1;
}
- EXIT_LOG (logbuffer);
- if (threadless)
- safe_send_threadless (profiler, logbuffer);
- else
- safe_send (profiler, logbuffer);
+ EXIT_LOG;
}
static gboolean
}
static void
-perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp, gboolean threadless)
+perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
{
PerfCounterAgent *pcagent;
- LogBuffer *logbuffer;
int size;
if (!counters_initialized)
mono_perfcounter_foreach (perfcounters_foreach, perfcounters);
- perfcounters_emit (profiler, threadless);
+ perfcounters_emit (profiler);
size =
- EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */
+ EVENT_SIZE /* event */
;
for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
size +=
LEB128_SIZE /* index */ +
- LEB128_SIZE /* type */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* value */
;
}
LEB128_SIZE /* stop marker */
;
- logbuffer = ensure_logbuf (size);
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (size);
+
+ emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
- ENTER_LOG (logbuffer, "perfcounters");
- emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE);
- emit_uvalue (logbuffer, timestamp);
for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
if (pcagent->deleted || !pcagent->updated)
continue;
emit_uvalue (logbuffer, pcagent->index);
- emit_uvalue (logbuffer, MONO_COUNTER_LONG);
+ emit_byte (logbuffer, MONO_COUNTER_LONG);
emit_svalue (logbuffer, pcagent->value);
pcagent->updated = 0;
}
emit_value (logbuffer, 0);
- EXIT_LOG (logbuffer);
- if (threadless)
- safe_send_threadless (profiler, logbuffer);
- else
- safe_send (profiler, logbuffer);
+ EXIT_LOG;
mono_os_mutex_unlock (&counters_mutex);
}
static void
-counters_and_perfcounters_sample (MonoProfiler *prof, gboolean threadless)
+counters_and_perfcounters_sample (MonoProfiler *prof)
{
- static uint64_t start = -1;
- uint64_t now;
-
- if (start == -1)
- start = current_time ();
+ uint64_t now = current_time ();
- now = current_time ();
- counters_sample (prof, (now - start) / 1000/ 1000, threadless);
- perfcounters_sample (prof, (now - start) / 1000/ 1000, threadless);
+ counters_sample (prof, now);
+ perfcounters_sample (prof, now);
}
#define COVERAGE_DEBUG(x) if (debug_coverage) {x}
static GPtrArray *coverage_data = NULL;
static int previous_offset = 0;
-typedef struct _MethodNode MethodNode;
-struct _MethodNode {
+typedef struct {
MonoLockFreeQueueNode node;
MonoMethod *method;
-};
+} MethodNode;
-typedef struct _CoverageEntry CoverageEntry;
-struct _CoverageEntry {
+typedef struct {
int offset;
int counter;
char *filename;
int line;
int column;
-};
+} CoverageEntry;
static void
free_coverage_entry (gpointer data, gpointer userdata)
MonoImage *image;
char *class_name;
const char *image_name, *method_name, *sig, *first_filename;
- LogBuffer *logbuffer;
guint i;
previous_offset = 0;
sig = sig ? sig : "";
method_name = method_name ? method_name : "";
- logbuffer = ensure_logbuf (
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
strlen (image_name) + 1 /* image name */ +
strlen (class_name) + 1 /* class name */ +
LEB128_SIZE /* method id */ +
LEB128_SIZE /* entries */
);
- ENTER_LOG (logbuffer, "coverage-methods");
- emit_byte (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
+ emit_event (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
emit_string (logbuffer, image_name, strlen (image_name) + 1);
emit_string (logbuffer, class_name, strlen (class_name) + 1);
emit_string (logbuffer, method_name, strlen (method_name) + 1);
emit_uvalue (logbuffer, method_id);
emit_value (logbuffer, coverage_data->len);
- EXIT_LOG (logbuffer);
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
for (i = 0; i < coverage_data->len; i++) {
CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[i];
- logbuffer = ensure_logbuf (
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
LEB128_SIZE /* method id */ +
LEB128_SIZE /* offset */ +
LEB128_SIZE /* line */ +
LEB128_SIZE /* column */
);
- ENTER_LOG (logbuffer, "coverage-statement");
- emit_byte (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
+ emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
emit_uvalue (logbuffer, method_id);
emit_uvalue (logbuffer, entry->offset);
emit_uvalue (logbuffer, entry->counter);
emit_uvalue (logbuffer, entry->line);
emit_uvalue (logbuffer, entry->column);
- EXIT_LOG (logbuffer);
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
}
method_id++;
const char *assembly_name;
int number_of_methods, partially_covered;
guint fully_covered;
- LogBuffer *logbuffer;
image = mono_class_get_image (klass);
assembly_name = mono_image_get_name (image);
/* We don't handle partial covered yet */
partially_covered = 0;
- logbuffer = ensure_logbuf (
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
strlen (assembly_name) + 1 /* assembly name */ +
strlen (class_name) + 1 /* class name */ +
LEB128_SIZE /* partially covered */
);
- ENTER_LOG (logbuffer, "coverage-class");
- emit_byte (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
+ emit_event (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
emit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);
emit_string (logbuffer, class_name, strlen (class_name) + 1);
emit_uvalue (logbuffer, number_of_methods);
emit_uvalue (logbuffer, fully_covered);
emit_uvalue (logbuffer, partially_covered);
- EXIT_LOG (logbuffer);
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
g_free (class_name);
}
MonoAssembly *assembly = (MonoAssembly *)value;
MonoProfiler *prof = (MonoProfiler *)userdata;
MonoImage *image = mono_assembly_get_image (assembly);
- LogBuffer *logbuffer;
const char *name, *guid, *filename;
int number_of_methods = 0, partially_covered = 0;
guint fully_covered = 0;
get_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);
- logbuffer = ensure_logbuf (
+ ENTER_LOG;
+
+ LogBuffer *logbuffer = ensure_logbuf (
EVENT_SIZE /* event */ +
strlen (name) + 1 /* name */ +
strlen (guid) + 1 /* guid */ +
LEB128_SIZE /* partially covered */
);
- ENTER_LOG (logbuffer, "coverage-assemblies");
- emit_byte (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
+ emit_event (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
emit_string (logbuffer, name, strlen (name) + 1);
emit_string (logbuffer, guid, strlen (guid) + 1);
emit_string (logbuffer, filename, strlen (filename) + 1);
emit_uvalue (logbuffer, number_of_methods);
emit_uvalue (logbuffer, fully_covered);
emit_uvalue (logbuffer, partially_covered);
- EXIT_LOG (logbuffer);
- safe_send (prof, logbuffer);
+ EXIT_LOG;
+
+ send_if_needed (prof);
}
static void
in_shutdown = 1;
#ifndef DISABLE_HELPER_THREAD
- counters_and_perfcounters_sample (prof, FALSE);
+ counters_and_perfcounters_sample (prof);
dump_coverage (prof);
}
#endif
- if (TLS_GET (LogBuffer, tlsbuffer))
- send_buffer (prof, TLS_GET (GPtrArray, tlsmethodlist), TLS_GET (LogBuffer, tlsbuffer));
-
- TLS_SET (tlsbuffer, NULL);
- TLS_SET (tlsmethodlist, NULL);
+ /*
+ * Ensure that we empty the LLS completely, even if some nodes are
+ * not immediately removed upon calling mono_lls_remove (), by
+ * iterating until the head is NULL.
+ */
+ while (profiler_thread_list.head) {
+ MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+ remove_thread (prof, thread, FALSE);
+ } MONO_LLS_FOREACH_SAFE_END
+ }
InterlockedWrite (&prof->run_dumper_thread, 0);
mono_os_sem_post (&prof->dumper_queue_sem);
cleanup_reusable_samples (prof);
+ /*
+ * Pump the entire hazard free queue to make sure that anything we allocated
+ * in the profiler will be freed. If we don't do this, the runtime could get
+ * around to freeing some items after the profiler has been unloaded, which
+ * would mean calling into functions in the profiler library, leading to a
+ * crash.
+ */
+ mono_thread_hazardous_try_free_all ();
+
+ g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why is the reader count still non-zero?");
+ g_assert (!InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why does someone still hold the exclusive lock?");
+
#if defined (HAVE_SYS_ZLIB)
if (prof->gzfile)
gzclose (prof->gzfile);
mono_os_mutex_destroy (&coverage_mutex);
}
+ PROF_TLS_FREE ();
+
+ free (prof->args);
free (prof);
}
int command_socket;
int len;
char buf [64];
- MonoThread *thread = NULL;
mono_threads_attach_tools_thread ();
mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
+ init_thread (FALSE);
+
//fprintf (stderr, "Server listening\n");
command_socket = -1;
while (1) {
}
#endif
- counters_and_perfcounters_sample (prof, TRUE);
+ counters_and_perfcounters_sample (prof);
+
+ buffer_lock_excl ();
+
+ sync_point (prof, SYNC_POINT_PERIODIC);
+
+ buffer_unlock_excl ();
tv.tv_sec = 1;
tv.tv_usec = 0;
if (FD_ISSET (prof->pipes [0], &rfds)) {
char c;
read (prof->pipes [0], &c, 1);
- if (thread)
- mono_thread_detach (thread);
if (do_debug)
fprintf (stderr, "helper shutdown\n");
#if USE_PERF_EVENTS
}
}
#endif
- safe_send_threadless (prof, ensure_logbuf (0));
+ safe_send_threadless (prof);
return NULL;
}
#if USE_PERF_EVENTS
continue;
if (FD_ISSET (perf_data [i].perf_fd, &rfds)) {
read_perf_mmap (prof, i);
- safe_send_threadless (prof, ensure_logbuf (0));
+ send_if_needed_threadless (prof);
}
}
}
continue;
}
buf [len] = 0;
- if (strcmp (buf, "heapshot\n") == 0) {
+ if (strcmp (buf, "heapshot\n") == 0 && hs_mode_ondemand) {
+ // Rely on the finalization callbacks invoking process_requests ().
heapshot_requested = 1;
- //fprintf (stderr, "perform heapshot\n");
- if (InterlockedRead (&runtime_inited) && !thread) {
- thread = mono_thread_attach (mono_get_root_domain ());
- /*fprintf (stderr, "attached\n");*/
- }
- if (thread) {
- process_requests (prof);
- mono_thread_detach (thread);
- thread = NULL;
- }
+ mono_gc_finalize_notify ();
}
continue;
}
}
#endif
+static void
+free_writer_entry (gpointer p)
+{
+ mono_lock_free_free (p, WRITER_ENTRY_BLOCK_SIZE);
+}
+
static gboolean
handle_writer_queue_entry (MonoProfiler *prof)
{
WriterQueueEntry *entry;
if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&prof->writer_queue))) {
- LogBuffer *method_buffer = NULL;
- gboolean new_methods = FALSE;
+ if (!entry->methods)
+ goto no_methods;
- if (entry->methods->len)
- method_buffer = create_buffer ();
+ LogBuffer *buf = NULL;
/*
* Encode the method events in a temporary log buffer that we
* flush to disk before the main buffer, ensuring that all
* methods have metadata emitted before they're referenced.
+ *
+ * We use a 'proper' thread-local buffer for this as opposed
+ * to allocating and freeing a buffer by hand because the call
+ * to mono_method_full_name () below may trigger class load
+ * events when it retrieves the signature of the method. So a
+ * thread-local buffer needs to exist when such events occur.
*/
for (guint i = 0; i < entry->methods->len; i++) {
- MethodInfo *info = (MethodInfo *)g_ptr_array_index (entry->methods, i);
+ MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
if (mono_conc_hashtable_lookup (prof->method_table, info->method))
- continue;
-
- new_methods = TRUE;
+ goto free_info; // This method already has metadata emitted.
/*
* Other threads use this hash table to get a general
void *cstart = info->ji ? mono_jit_info_get_code_start (info->ji) : NULL;
int csize = info->ji ? mono_jit_info_get_code_size (info->ji) : 0;
- method_buffer = ensure_logbuf_inner (method_buffer,
+ buf = ensure_logbuf_unsafe (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* time */ +
LEB128_SIZE /* method */ +
LEB128_SIZE /* start */ +
LEB128_SIZE /* size */ +
nlen /* name */
);
- emit_byte (method_buffer, TYPE_JIT | TYPE_METHOD);
- emit_time (method_buffer, info->time);
- emit_method_inner (method_buffer, info->method);
- emit_ptr (method_buffer, cstart);
- emit_value (method_buffer, csize);
+ emit_event_time (buf, TYPE_JIT | TYPE_METHOD, info->time);
+ emit_method_inner (buf, info->method);
+ emit_ptr (buf, cstart);
+ emit_value (buf, csize);
- memcpy (method_buffer->cursor, name, nlen);
- method_buffer->cursor += nlen;
+ memcpy (buf->cursor, name, nlen);
+ buf->cursor += nlen;
mono_free (name);
+
+ free_info:
free (info);
}
g_ptr_array_free (entry->methods, TRUE);
- if (new_methods) {
- for (LogBuffer *iter = method_buffer; iter; iter = iter->next)
- iter->thread_id = 0;
-
- dump_buffer (prof, method_buffer);
- } else if (method_buffer)
- free_buffer (method_buffer, method_buffer->size);
+ if (buf) {
+ dump_buffer_threadless (prof, buf);
+ init_buffer_state (PROF_TLS_GET ());
+ }
+ no_methods:
dump_buffer (prof, entry->buffer);
- mono_thread_hazardous_try_free (entry, free);
+ mono_thread_hazardous_try_free (entry, free_writer_entry);
return TRUE;
}
dump_header (prof);
+ MonoProfilerThread *thread = init_thread (FALSE);
+
while (InterlockedRead (&prof->run_writer_thread)) {
mono_os_sem_wait (&prof->writer_queue_sem, MONO_SEM_FLAGS_NONE);
handle_writer_queue_entry (prof);
/* Drain any remaining entries on shutdown. */
while (handle_writer_queue_entry (prof));
+ free_buffer (thread->buffer, thread->buffer->size);
+ deinit_thread (thread);
+
mono_thread_info_detach ();
return NULL;
void *address = sample->frames [i].base_address;
if (!method) {
- g_assert (domain);
- g_assert (address);
+ g_assert (domain && "What happened to the domain pointer?");
+ g_assert (address && "What happened to the instruction pointer?");
MonoJitInfo *ji = mono_jit_info_table_find (domain, (char *) address);
}
}
- LogBuffer *logbuffer = ensure_logbuf (
+ LogBuffer *logbuffer = ensure_logbuf_unsafe (
EVENT_SIZE /* event */ +
- LEB128_SIZE /* type */ +
- LEB128_SIZE /* time */ +
+ BYTE_SIZE /* type */ +
LEB128_SIZE /* tid */ +
LEB128_SIZE /* count */ +
1 * (
) +
LEB128_SIZE /* managed count */ +
sample->count * (
- LEB128_SIZE /* method */ +
- LEB128_SIZE /* il offset */ +
- LEB128_SIZE /* native offset */
+ LEB128_SIZE /* method */
)
);
- emit_byte (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT);
- emit_value (logbuffer, sample_type);
- emit_uvalue (logbuffer, prof->startup_time + sample->elapsed * 10000);
+ emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
+ emit_byte (logbuffer, sample_type);
emit_ptr (logbuffer, (void *) sample->tid);
emit_value (logbuffer, 1);
/* new in data version 6 */
emit_uvalue (logbuffer, sample->count);
- for (int i = 0; i < sample->count; ++i) {
+ for (int i = 0; i < sample->count; ++i)
emit_method (prof, logbuffer, sample->frames [i].method);
- emit_svalue (logbuffer, 0); /* il offset will always be 0 from now on */
- emit_svalue (logbuffer, sample->frames [i].offset);
- }
mono_thread_hazardous_try_free (sample, reuse_sample_hit);
dump_unmanaged_coderefs (prof);
- if (logbuffer->next)
- safe_send_threadless (prof, logbuffer);
+ send_if_needed_threadless (prof);
}
return FALSE;
mono_threads_attach_tools_thread ();
mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
+ MonoProfilerThread *thread = init_thread (FALSE);
+
while (InterlockedRead (&prof->run_dumper_thread)) {
mono_os_sem_wait (&prof->dumper_queue_sem, MONO_SEM_FLAGS_NONE);
handle_dumper_queue_entry (prof);
/* Drain any remaining entries on shutdown. */
while (handle_dumper_queue_entry (prof));
- safe_send_threadless (prof, ensure_logbuf (0));
+ safe_send_threadless (prof);
+ deinit_thread (thread);
mono_thread_info_detach ();
static void
runtime_initialized (MonoProfiler *profiler)
{
+ InterlockedWrite (&runtime_inited, 1);
+
#ifndef DISABLE_HELPER_THREAD
if (hs_mode_ondemand || need_helper_thread) {
if (!start_helper_thread (profiler))
start_writer_thread (profiler);
start_dumper_thread (profiler);
- InterlockedWrite (&runtime_inited, 1);
+ mono_counters_register ("Sample hits", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_hits);
+ mono_counters_register ("Sample flushes", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_flushes);
+ mono_counters_register ("Sample events allocated", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_allocations);
+ mono_counters_register ("Log buffers allocated", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &buffer_allocations);
+ mono_counters_register ("Thread start events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &thread_starts);
+ mono_counters_register ("Thread stop events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &thread_ends);
+ mono_counters_register ("Domain load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &domain_loads);
+ mono_counters_register ("Domain unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &domain_unloads);
+ mono_counters_register ("Context load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &context_loads);
+ mono_counters_register ("Context unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &context_unloads);
+ mono_counters_register ("Assembly load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &assembly_loads);
+ mono_counters_register ("Assembly unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &assembly_unloads);
+ mono_counters_register ("Image load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &image_loads);
+ mono_counters_register ("Image unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &image_unloads);
+ mono_counters_register ("Class load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &class_loads);
+ mono_counters_register ("Class unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &class_unloads);
+
#ifndef DISABLE_HELPER_THREAD
counters_init (profiler);
- counters_sample (profiler, 0, FALSE);
+ counters_sample (profiler, 0);
#endif
/* ensure the main thread data and startup are available soon */
- safe_send (profiler, ensure_logbuf (0));
+ safe_send (profiler);
}
static MonoProfiler*
-create_profiler (const char *filename, GPtrArray *filters)
+create_profiler (const char *args, const char *filename, GPtrArray *filters)
{
MonoProfiler *prof;
char *nf;
int force_delete = 0;
prof = (MonoProfiler *)calloc (1, sizeof (MonoProfiler));
+ prof->args = pstrdup (args);
prof->command_port = command_port;
if (filename && *filename == '-') {
force_delete = 1;
prof->gzfile = gzdopen (fileno (prof->file), "wb");
#endif
#if USE_PERF_EVENTS
- if (sample_type && !do_mono_sample)
+ if (sample_type && sample_freq && !do_mono_sample)
need_helper_thread = setup_perf_event ();
if (!perf_data) {
/* FIXME: warn if different freq or sample type */
#endif
+ g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
+
+ // FIXME: We should free this stuff too.
+ mono_lock_free_allocator_init_size_class (&prof->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
+ mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class);
+
mono_lock_free_queue_init (&prof->writer_queue);
mono_os_sem_init (&prof->writer_queue_sem, 0);
MONO_PROFILE_ENTER_LEAVE|MONO_PROFILE_JIT_COMPILATION|MONO_PROFILE_EXCEPTIONS|
MONO_PROFILE_MONITOR_EVENTS|MONO_PROFILE_MODULE_EVENTS|MONO_PROFILE_GC_ROOTS|
MONO_PROFILE_INS_COVERAGE|MONO_PROFILE_APPDOMAIN_EVENTS|MONO_PROFILE_CONTEXT_EVENTS|
- MONO_PROFILE_ASSEMBLY_EVENTS;
+ MONO_PROFILE_ASSEMBLY_EVENTS|MONO_PROFILE_GC_FINALIZATION;
max_allocated_sample_hits = mono_cpu_count () * 1000;
- mono_counters_register ("Sample hits", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_hits);
- mono_counters_register ("Sample flushes", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_flushes);
- mono_counters_register ("Sample events allocated", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &sample_allocations);
- mono_counters_register ("Log buffers allocated", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &buffer_allocations);
- mono_counters_register ("Thread start events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &thread_starts);
- mono_counters_register ("Thread stop events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &thread_ends);
- mono_counters_register ("Domain load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &domain_loads);
- mono_counters_register ("Domain unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &domain_unloads);
- mono_counters_register ("Context load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &context_loads);
- mono_counters_register ("Context unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &context_unloads);
- mono_counters_register ("Assembly load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &assembly_loads);
- mono_counters_register ("Assembly unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &assembly_unloads);
- mono_counters_register ("Image load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &image_loads);
- mono_counters_register ("Image unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &image_unloads);
- mono_counters_register ("Class load events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &class_loads);
- mono_counters_register ("Class unload events", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &class_unloads);
-
p = desc;
if (strncmp (p, "log", 3))
usage (1);
utils_init (fast_time);
- prof = create_profiler (filename, filters);
- if (!prof)
+ PROF_TLS_INIT ();
+
+ prof = create_profiler (desc, filename, filters);
+ if (!prof) {
+ PROF_TLS_FREE ();
return;
+ }
- init_thread ();
+ mono_lls_init (&profiler_thread_list, NULL);
+
+ init_thread (TRUE);
mono_profiler_install (prof, log_shutdown);
mono_profiler_install_gc (gc_event, gc_resize);
mono_profiler_install_allocation (gc_alloc);
mono_profiler_install_gc_moves (gc_moves);
mono_profiler_install_gc_roots (gc_handle, gc_roots);
+ mono_profiler_install_gc_finalize (finalize_begin, finalize_object_begin, finalize_object_end, finalize_end);
mono_profiler_install_appdomain (NULL, domain_loaded, domain_unloaded, NULL);
mono_profiler_install_appdomain_name (domain_name);
mono_profiler_install_context (context_loaded, context_unloaded);
if (do_coverage)
mono_profiler_install_coverage_filter (coverage_filter);
- if (do_mono_sample && sample_type == SAMPLE_CYCLES && !only_counters) {
+ if (do_mono_sample && sample_type == SAMPLE_CYCLES && sample_freq && !only_counters) {
events |= MONO_PROFILE_STATISTICAL;
mono_profiler_set_statistical_mode (sampling_mode, sample_freq);
mono_profiler_install_statistical (mono_sample_hit);
}
mono_profiler_set_events ((MonoProfileFlags)events);
-
- TLS_INIT (tlsbuffer);
- TLS_INIT (tlsmethodlist);
}
#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
added TYPE_GC_HANDLE_{CREATED,DESTROYED}_BT
TYPE_JIT events are no longer guaranteed to have code start/size info (can be zero)
* version 12: added MONO_COUNTER_PROFILER
+ * version 13: added MONO_GC_EVENT_{PRE_STOP_WORLD_LOCKED,POST_START_WORLD_UNLOCKED}
+ added TYPE_META + TYPE_SYNC_POINT
+ removed il and native offset in TYPE_SAMPLE_HIT
+ methods in backtraces are now encoded as proper method pointers
+ removed flags in backtrace format
+ removed flags in metadata events
+ changed the following fields to a single byte rather than leb128
+ TYPE_GC_EVENT: event_type, generation
+ TYPE_HEAP_ROOT: root_type
+ TYPE_JITHELPER: type
+ TYPE_SAMPLE_HIT: sample_type
+ TYPE_CLAUSE: clause_type
+ TYPE_SAMPLE_COUNTERS_DESC: type, unit, variance
+ TYPE_SAMPLE_COUNTERS: type
+ added time fields to all events that were missing one
+ TYPE_HEAP_OBJECT
+ TYPE_HEAP_ROOT
+ TYPE_SAMPLE_USYM
+ TYPE_SAMPLE_COUNTERS_DESC
+ TYPE_COVERAGE_METHOD
+ TYPE_COVERAGE_STATEMENT
+ TYPE_COVERAGE_CLASS
+ TYPE_COVERAGE_ASSEMBLY
+ moved the time field in TYPE_SAMPLE_HIT to right after the event byte, now encoded as a regular time field
+ changed the time field in TYPE_SAMPLE_COUNTERS to be encoded as a regular time field (in nanoseconds)
+ added TYPE_GC_FINALIZE_{START,END,OBJECT_START,OBJECT_END}
*/
enum {
TYPE_SAMPLE,
TYPE_RUNTIME,
TYPE_COVERAGE,
+ TYPE_META,
/* extended type for TYPE_HEAP */
TYPE_HEAP_START = 0 << 4,
TYPE_HEAP_END = 1 << 4,
/* 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,
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,
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 {
process_id (void)
{
#ifdef HOST_WIN32
- return 0; /* FIXME */
+ return GetCurrentProcessId ();
#else
return (uintptr_t)getpid ();
#endif
/* 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
pinvoke_ppcf.cs \
pinvoke_ppcd.cs \
bug-29585.cs \
- priority.cs
+ priority.cs \
+ abort-cctor.cs \
+ reference-loader.cs
if INSTALL_MOBILE_STATIC
BASE_TEST_CS_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)
STRESS_TESTS=$(STRESS_TESTS_SRC:.cs=.exe)
-PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX))
-PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX))
+PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX)) \
+ $(PREREQ_IL_DLL_SRC:.il=.dll$(PLATFORM_AOT_SUFFIX))
+PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX)) \
+ $(PREREQ_CS_DLL_SRC:.cs=.dll$(PLATFORM_AOT_SUFFIX))
EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \
$(BENCHSRC) $(STRESS_TESTS_SRC) stress-runner.pl $(PREREQ_IL_SRC) $(PREREQ_CS_SRC)
%.exe: %.cs $(TEST_DRIVER_DEPEND)
$(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll $(TEST_DRIVER_HARD_KILL_FEATURE) -out:$@ $<
+%.dll: %.cs
+ $(MCS) -r:System.dll -target:library -out:$@ $<
+
+TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll
+ $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $<
+
%.exe$(PLATFORM_AOT_SUFFIX): %.exe
$(RUNTIME) $(AOT_BUILD_FLAGS) $<
--- /dev/null
+using System.Runtime.CompilerServices;
+
+[assembly: ReferenceAssemblyAttribute]
+
+public class X {
+ public int Y;
+}
--- /dev/null
+// An assembly that refereces the TestingReferenceAssembly
+
+class Z : X {
+ public Z () {
+ Y = 1;
+ }
+}
--- /dev/null
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Runtime.CompilerServices;
+
+class Driver
+{
+ public static ManualResetEvent mre1 = new ManualResetEvent (false);
+ public static ManualResetEvent mre2 = new ManualResetEvent (false);
+
+ class StaticConstructor1
+ {
+ internal static bool gotToEnd, caughtException;
+ static StaticConstructor1 ()
+ {
+ try {
+ Console.WriteLine ("StaticConstructor1.StaticConstructor1 (1)");
+ Driver.mre1.Set ();
+ var sw = Stopwatch.StartNew ();
+ Thread.Sleep (1000);
+ sw.Stop ();
+ typeof (string).GetMethods ();
+ //XXX we assume that if we slept less than 900ms we got aborted
+ if (sw.ElapsedMilliseconds < 900)
+ throw new Exception ("Bad abort broke our sleep");
+ Console.WriteLine ("StaticConstructor1.StaticConstructor1 (2) waited {0}", sw.ElapsedMilliseconds);
+ gotToEnd = true;
+ } catch (Exception e) {
+ caughtException = true;
+ throw;
+ }
+ }
+
+ public static void Init ()
+ {
+ Console.WriteLine ("StaticConstructor1.Init");
+ }
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static void IsStaticConstructor1Viable () {
+ new StaticConstructor1 ();
+ Console.WriteLine ("Did it get to the end? {0} Did it catch an exception {1}", StaticConstructor1.gotToEnd, StaticConstructor1.caughtException);
+ if (!StaticConstructor1.gotToEnd) /* the TAE must not land during a .cctor */
+ Environment.Exit (1);
+ if (StaticConstructor1.caughtException)
+ Environment.Exit (1);
+
+ }
+
+ static void Test1 ()
+ {
+ Console.WriteLine ("Test 1:");
+
+ Driver.mre1.Reset ();
+ Driver.mre2.Reset ();
+
+ Thread thread = new Thread (() => {
+ try {
+ StaticConstructor1.Init ();
+ } catch (Exception e) {
+ Console.WriteLine ("StaticConstructor1::init caught exception {0}", e);
+
+ if (!(e is ThreadAbortException))
+ throw;
+ }
+ });
+
+ thread.Start ();
+
+ Driver.mre1.WaitOne ();
+
+ // The ThreadAbortException should land while in
+ // the StaticConstructor1.cctor. The exception should
+ // be queued, and be rethrown when exiting the cctor.
+ thread.Abort ();
+
+ thread.Join ();
+
+ //is StaticConstructor1 viable?
+ try {
+ IsStaticConstructor1Viable ();
+ Console.WriteLine ("StaticConstructor1 is viable"); /* a TAE doesn't make a type unusable */
+ } catch (TypeInitializationException e) {
+ Console.WriteLine ("StaticConstructor1 not viable");
+ Environment.Exit (1);
+ }
+ }
+
+ class StaticConstructor2Exception : Exception {}
+
+ class StaticConstructor2
+ {
+ static StaticConstructor2 ()
+ {
+ Console.WriteLine ("StaticConstructor2.StaticConstructor2 (1)");
+ Driver.mre1.Set ();
+ throw new StaticConstructor2Exception ();
+ /* Unreachable */
+ Driver.mre2.Set ();
+ Console.WriteLine ("StaticConstructor2.StaticConstructor2 (2)");
+ }
+
+ public static void Init ()
+ {
+ Console.WriteLine ("StaticConstructor2.Init");
+ }
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static void IsStaticConstructor2Viable () {
+ new StaticConstructor2 ();
+ }
+
+
+ static void Test2 ()
+ {
+ Console.WriteLine ("Test 2:");
+
+ Driver.mre1.Reset ();
+ Driver.mre2.Reset ();
+
+ Thread thread = new Thread (() => {
+ try {
+ StaticConstructor2.Init ();
+ } catch (TypeInitializationException e) {
+ Console.WriteLine (e);
+
+ if (!(e.InnerException is StaticConstructor2Exception))
+ throw;
+ }
+ });
+
+ thread.Start ();
+
+ Driver.mre1.WaitOne ();
+
+ // A InvalidOperationException should be thrown while in
+ // the StaticConstructor2.cctor. The exception should
+ // be wrapped in a TypeInitializationException.
+
+ if (Driver.mre2.WaitOne (500)) {
+ /* We shouldn't reach Driver.mre.Set () in StaticConstructor2.cctor */
+ Environment.Exit (1);
+ }
+
+ thread.Join ();
+
+ //is StaticConstructor2 viable?
+ try {
+ IsStaticConstructor2Viable ();
+ Console.WriteLine ("StaticConstructor2 is viable");
+ /* A regular exception escaping the .cctor makes the type not usable */
+ Environment.Exit (1);
+ } catch (TypeInitializationException e) {
+ Console.WriteLine ("StaticConstructor2 not viable");
+ }
+
+ }
+
+ class StaticConstructor3
+ {
+ static StaticConstructor3 ()
+ {
+ Console.WriteLine ("StaticConstructor3.StaticConstructor3 (1)");
+ Driver.mre1.Set ();
+ Thread.CurrentThread.Abort ();
+ /* Unreachable */
+ Driver.mre2.Set ();
+ Console.WriteLine ("StaticConstructor3.StaticConstructor3 (2)");
+ Environment.Exit (1);
+ }
+
+ public static void Init ()
+ {
+ Console.WriteLine ("StaticConstructor3.Init");
+ }
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static void IsStaticConstructor3Viable () {
+ new StaticConstructor3 ();
+ }
+
+ static void Test3 ()
+ {
+ Console.WriteLine ("Test 3:");
+
+ Driver.mre1.Reset ();
+ Driver.mre2.Reset ();
+
+ Thread thread = new Thread (() => {
+ try {
+ StaticConstructor3.Init ();
+ Console.WriteLine ("cctor3 didn't throw?!?!");
+ /* StaticConstructor3 self aborted */
+ Environment.Exit (1);
+ } catch (ThreadAbortException e) {
+ Console.WriteLine ("TEST 3: aborted {0}", e);
+ }
+ });
+
+ thread.Start ();
+
+ Driver.mre1.WaitOne ();
+
+ // A InvalidOperationException should be thrown while in
+ // the StaticConstructor2.cctor. The exception should
+ // be wrapped in a TypeInitializationException.
+
+ thread.Join ();
+
+ //is StaticConstructor2 viable?
+ try {
+ IsStaticConstructor3Viable ();
+ Console.WriteLine ("StaticConstructor3 is viable");
+ /* A regular exception escaping the .cctor makes the type not usable */
+ Environment.Exit (1);
+ } catch (TypeInitializationException e) {
+ Console.WriteLine ("StaticConstructor3 not viable");
+ }
+ }
+
+
+
+
+
+ class StaticConstructor4
+ {
+ internal static bool gotToEnd, caughtException;
+
+ static StaticConstructor4 ()
+ {
+ try {
+ Console.WriteLine ("StaticConstructor4.StaticConstructor4 (1)");
+ Driver.mre1.Set ();
+ var sw = Stopwatch.StartNew ();
+ Thread.Sleep (1000);
+ sw.Stop ();
+ typeof (string).GetMethods ();
+ //XXX we assume that if we slept less than 900ms we got aborted
+ if (sw.ElapsedMilliseconds < 900)
+ throw new Exception ("Bad abort broke our sleep");
+ Console.WriteLine ("StaticConstructor4.StaticConstructor4 (2) waited {0}", sw.ElapsedMilliseconds);
+ gotToEnd = true;
+ } catch (Exception e) {
+ caughtException = true;
+ throw;
+ }
+ }
+
+ public static void Init ()
+ {
+ Console.WriteLine ("StaticConstructor4.Init");
+ }
+ }
+
+ static bool got_to_the_end_of_the_finally = false;
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static void IsStaticConstructor4Viable () {
+ new StaticConstructor4 ();
+ Console.WriteLine ("IsStaticConstructor4Viable: Did it get to the end? {0} Did it catch an exception {1} and end of the finally block {2}", StaticConstructor4.gotToEnd, StaticConstructor4.caughtException, got_to_the_end_of_the_finally);
+ if (!StaticConstructor4.gotToEnd) /* the TAE must not land during a .cctor */
+ Environment.Exit (1);
+ if (StaticConstructor4.caughtException)
+ Environment.Exit (1);
+ }
+
+ static void Test4 ()
+ {
+ Console.WriteLine ("Test 4:");
+
+ Driver.mre1.Reset ();
+ Driver.mre2.Reset ();
+
+ Thread thread = new Thread (() => {
+ try {
+
+ try {
+ } finally {
+ StaticConstructor4.Init ();
+ Console.WriteLine ("Test 4: After the cctor");
+ got_to_the_end_of_the_finally = true;
+ }
+ } catch (Exception e) {
+ Console.WriteLine ("StaticConstructor4::init caught exception {0}", e);
+ if (!(e is ThreadAbortException))
+ throw;
+ if (!got_to_the_end_of_the_finally)
+ throw new Exception ("Test 4: did not get to the end of the cctor");
+ }
+ });
+
+ thread.Start ();
+
+ Driver.mre1.WaitOne ();
+
+ // The ThreadAbortException should land while in
+ // the StaticConstructor4.cctor. The exception should
+ // be queued, and be rethrown when exiting the cctor.
+ thread.Abort ();
+
+ thread.Join ();
+
+ if (!got_to_the_end_of_the_finally) {
+ Console.WriteLine ("Did not get to the end of test 4 cctor");
+ Environment.Exit (1);
+ }
+
+ //is StaticConstructor4viable?
+ try {
+ IsStaticConstructor4Viable ();
+ Console.WriteLine ("StaticConstructor4 is viable"); /* a TAE doesn't make a type unusable */
+ } catch (TypeInitializationException e) {
+ Console.WriteLine ("StaticConstructor4 not viable");
+ Environment.Exit (1);
+ }
+ }
+
+
+
+ public static int Main ()
+ {
+ Test1 ();
+ Test2 ();
+ Test3 ();
+ Test4 ();
+ Console.WriteLine ("done, all things good");
+ return 0;
+ }
+}
\ No newline at end of file
return sa4;
}
+typedef struct {
+ int array [3];
+} FixedArrayStruct;
+
+LIBTEST_API int STDCALL
+mono_test_marshal_fixed_array (FixedArrayStruct s)
+{
+ return s.array [0] + s.array [1] + s.array [2];
+}
using System.Runtime.CompilerServices;
using System.Reflection.Emit;
-public class Tests {
+public unsafe class Tests {
public int int_field;
else
return 0;
}
+
+ [StructLayout(LayoutKind.Explicit, Size = 12)]
+ public struct FixedArrayStruct {
+ [FieldOffset(0)]
+ public fixed int array[3];
+ }
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_fixed_array")]
+ public static extern int mono_test_marshal_fixed_array (FixedArrayStruct s);
+
+ public static unsafe int test_6_fixed_array_struct () {
+ var s = new FixedArrayStruct ();
+ s.array [0] = 1;
+ s.array [1] = 2;
+ s.array [2] = 3;
+
+ return mono_test_marshal_fixed_array (s);
+ }
}
--- /dev/null
+//
+// 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;
+ }
+
+}
var heads = new Bridge [FAN_OUT];
for (int i = 0; i < FAN_OUT; ++i)
heads [i] = new Bridge ();
- var multiplexer = new Bridge [FAN_OUT];
- for (int i = 0; i < FAN_OUT; ++i)
- {
- heads [i].Links.Add (multiplexer);
- multiplexer [i] = new Bridge ();
+
+ // We make five identical multiplexers to verify Tarjan-bridge can merge them together correctly.
+ var MULTIPLEXER_COUNT = 5;
+ Bridge[] multiplexer0 = null;
+ for(int m = 0; m < MULTIPLEXER_COUNT; m++) {
+ var multiplexer = new Bridge [FAN_OUT];
+ if (m == 0) {
+ multiplexer0 = multiplexer;
+ for (int i = 0; i < FAN_OUT; ++i)
+ {
+ heads [i].Links.Add (multiplexer);
+ multiplexer [i] = new Bridge ();
+ }
+ } else {
+ for (int i = 0; i < FAN_OUT; ++i)
+ {
+ heads [i].Links.Add (multiplexer);
+ multiplexer [i] = multiplexer0 [i];
+ }
+ }
}
- Console.WriteLine ("-double fan done-");
+
+ Console.WriteLine ("-double fan x5 done-");
}
/*
#include "utils/mono-threads.h"
#include "utils/mono-conc-hashtable.h"
#include "utils/checked-build.h"
+#include "utils/w32handle.h"
#include <stdlib.h>
#include <string.h>
memset (&ticallbacks, 0, sizeof (ticallbacks));
ticallbacks.thread_state_init = thread_state_init;
mono_threads_runtime_init (&ticallbacks);
+#ifndef HOST_WIN32
+ mono_w32handle_init ();
+#endif
mono_thread_info_attach ((gpointer)&cb);
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);
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;
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;
atomic.c \
mono-hwcap.h \
mono-hwcap.c \
+ mono-hwcap-vars.h \
bsearch.h \
bsearch.c \
mono-signal-handler.h \
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)
#include "config.h"
#include <glib.h>
+#include <mono/utils/mono-membar.h>
/*
The current Nexus 7 arm-v7a fails with:
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
-#include <mono/utils/mono-membar.h>
/* mingw is missing InterlockedCompareExchange64 () from winbase.h */
#if HAVE_DECL_INTERLOCKEDCOMPAREEXCHANGE64==0
/* 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)
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;
}
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)
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)
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)
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__))
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
InterlockedExchange64 (dst, val);
}
-#elif defined(__ia64__)
-
-#ifdef __INTEL_COMPILER
-#include <ia64intrin.h>
-#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
typedef struct {
gpointer p;
MonoHazardousFreeFunc free_func;
- HazardFreeLocking locking;
} DelayedFreeItem;
/* The hazard table */
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;
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
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);
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
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); \
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);
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
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;
#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__*/
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;
* 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 <sys/auxv.h>
#include <stdio.h>
#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)
{
}
#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);
-}
+++ /dev/null
-#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__ */
/*
- * 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)
-{
-}
+++ /dev/null
-#ifndef __MONO_UTILS_HWCAP_ARM64_H__
-#define __MONO_UTILS_HWCAP_ARM64_H__
-
-#include "mono/utils/mono-hwcap.h"
-
-#endif
--- /dev/null
+/*
+ * 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)
+{
+}
* 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)
{
}
+++ /dev/null
-#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__ */
* 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)
{
}
+++ /dev/null
-#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__ */
* 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 <string.h>
#include <sys/auxv.h>
#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)
{
}
#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);
-}
+++ /dev/null
-#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__ */
* 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 <signal.h>
-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;
}
+++ /dev/null
-#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__ */
* 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 <string.h>
-
#if !defined(__linux__)
#include <sys/systeminfo.h>
#else
#include <unistd.h>
#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.
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);
-}
--- /dev/null
+#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
* 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 <unistd.h>
#endif
-
#if defined(_MSC_VER)
#include <intrin.h>
#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)
{
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);
-}
+++ /dev/null
-#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__ */
#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
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");
}
#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.
* 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
}
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;
/*
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;
*/
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;
/*
/*
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
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);
/*
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);
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;
}
}
typedef struct {
MonoLinkedListSetNode *head;
void (*free_node_func)(void *);
- HazardFreeLocking locking;
} MonoLinkedListSet;
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)
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__) { \
#else
#include <process.h>
#endif
-#include "mono-logger.h"
+#include "mono-logger-internals.h"
static FILE *logFile = NULL;
static void *logUserData = NULL;
* @vargs - Variable argument list
*/
void
-mono_log_write_logfile(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *format, va_list args)
+mono_log_write_logfile (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message)
{
time_t t;
- char logTime[80],
- logMessage[512];
- pid_t pid;
- int iLog = 0;
- size_t nLog;
if (logFile == NULL)
logFile = stdout;
if (hdr) {
+ pid_t pid;
+ char logTime [80];
+
#ifndef HOST_WIN32
struct tm tod;
time(&t);
pid = _getpid();
strftime(logTime, sizeof(logTime), "%F %T", tod);
#endif
- iLog = sprintf(logMessage, "%s level[%c] mono[%d]: ",
- logTime,mapLogFileLevel(level),pid);
+ fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message);
+ } else {
+ fprintf (logFile, "%s%s%s\n",
+ log_domain != NULL ? log_domain : "",
+ log_domain != NULL ? ": " : "",
+ message);
}
- nLog = sizeof(logMessage) - iLog - 2;
- vsnprintf(logMessage+iLog, nLog, format, args);
- iLog = strlen(logMessage);
- logMessage[iLog++] = '\n';
- logMessage[iLog++] = '\0';
- fputs(logMessage, logFile);
+
fflush(logFile);
if (level == G_LOG_FLAG_FATAL)
#include <errno.h>
#include <time.h>
#include <sys/time.h>
-#include "mono-logger.h"
+#include "mono-logger-internals.h"
static void *logUserData = NULL;
}
/**
- * mono_log_write_logfile
+ * mono_log_write_syslog
*
* Write data to the log file.
*
* @vargs - Variable argument list
*/
void
-mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *format, va_list args)
+mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message)
{
- vsyslog(mapSyslogLevel(level), format, args);
+ syslog (mapSyslogLevel(level), "%s", message);
if (level == G_LOG_FLAG_FATAL)
abort();
#include <errno.h>
#include <time.h>
#include <process.h>
-#include "mono-logger.h"
+#include "mono-logger-internals.h"
static FILE *logFile = NULL;
static void *logUserData = NULL;
* @vargs - Variable argument list
*/
void
-mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *format, va_list args)
+mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message)
{
time_t t;
- struct tm *tod;
- char logTime[80],
- logMessage[512];
pid_t pid;
- int iLog = 0;
- size_t nLog;
+ char logTime [80];
if (logFile == NULL)
- mono_log_open_syslog(NULL, NULL);
+ logFile = stdout;
+ struct tm *tod;
time(&t);
tod = localtime(&t);
pid = _getpid();
- strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", tod);
- iLog = sprintf(logMessage, "%s level[%c] mono[%d]: ",
- logTime,mapLogFileLevel(level),pid);
- nLog = sizeof(logMessage) - iLog - 2;
- vsnprintf(logMessage+iLog, nLog, format, args);
- iLog = strlen(logMessage);
- logMessage[iLog++] = '\n';
- logMessage[iLog++] = 0;
- fputs(logMessage, logFile);
+ strftime(logTime, sizeof(logTime), "%F %T", tod);
+
+ fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message);
+
fflush(logFile);
if (level == G_LOG_FLAG_FATAL)
#endif
+/* Internal logging API */
+typedef void (*MonoLoggerOpen) (const char *, void *);
+typedef void (*MonoLoggerWrite) (const char *, GLogLevelFlags, mono_bool, const char *);
+typedef void (*MonoLoggerClose) (void);
+
+typedef struct _MonoLogCallParm_ {
+ MonoLoggerOpen opener; /* Routine to open logging */
+ MonoLoggerWrite writer; /* Routine to write log data */
+ MonoLoggerClose closer; /* Routine to close logging */
+ char *dest; /* Log destination */
+ void *user_data; /* User data from legacy handler */
+ mono_bool header; /* Whether we want pid/time/date in log message */
+} MonoLogCallParm;
+
+void mono_trace_set_log_handler_internal (MonoLogCallParm *callback, void *user_data);
+void mono_trace_set_logdest_string (const char *value);
+void mono_trace_set_logheader_string (const char *value);
+
+void mono_log_open_syslog (const char *, void *);
+void mono_log_write_syslog (const char *, GLogLevelFlags, mono_bool, const char *);
+void mono_log_close_syslog (void);
+
+void mono_log_open_logfile (const char *, void *);
+void mono_log_write_logfile (const char *, GLogLevelFlags, mono_bool, const char *);
+void mono_log_close_logfile (void);
G_END_DECLS
typedef struct {
MonoLogCallback legacy_callback;
gpointer user_data;
-} legacyLoggerUserData;
+} UserSuppliedLoggerUserData;
/**
* mono_trace_init:
void
mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args)
{
+ char *log_message;
if (level_stack == NULL) {
mono_trace_init ();
if(level > mono_internal_current_level || !(mask & mono_internal_current_mask))
return;
}
- if (logCallback.opener == NULL) {
- logCallback.opener = mono_log_open_logfile;
- logCallback.writer = mono_log_write_logfile;
- logCallback.closer = mono_log_close_logfile;
- logCallback.opener(NULL, NULL);
- }
- logCallback.writer(mono_log_domain, level, logCallback.header, format, args);
+ g_assert (logCallback.opener); // mono_trace_init should have provided us with one!
+
+ if (g_vasprintf (&log_message, format, args) < 0)
+ return;
+ logCallback.writer (mono_log_domain, level, logCallback.header, log_message);
+ g_free (log_message);
}
/**
* logging. We ignore the header request as legacy handlers never had headers.
*/
static void
-callback_adapter(const char *domain, GLogLevelFlags level, mono_bool fatal, const char *fmt, va_list args)
+callback_adapter (const char *domain, GLogLevelFlags level, mono_bool fatal, const char *message)
{
- legacyLoggerUserData *ll = (legacyLoggerUserData *) logCallback.user_data;
- const char *msg = g_strdup_vprintf (fmt, args);
+ UserSuppliedLoggerUserData *ll =logCallback.user_data;
- ll->legacy_callback (domain, log_level_get_name(level), msg, fatal, ll->user_data);
- g_free ((void *) msg);
+ ll->legacy_callback (domain, log_level_get_name(level), message, fatal, ll->user_data);
+}
+
+static void
+eglib_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
+{
+ UserSuppliedLoggerUserData *ll = logCallback.user_data;
+
+ ll->legacy_callback (log_domain, log_level_get_name (log_level), message, log_level & G_LOG_LEVEL_ERROR, ll->user_data);
}
/**
legacy_closer(void)
{
if (logCallback.user_data != NULL) {
- g_free (logCallback.user_data); /* This is a LegacyLoggerUserData struct */
+ g_free (logCallback.user_data); /* This is a UserSuppliedLoggerUserData struct */
logCallback.opener = NULL;
logCallback.writer = NULL;
logCallback.closer = NULL;
*
* The log handler replaces the default runtime logger. All logging requests with be routed to it.
* If the fatal argument in the callback is true, the callback must abort the current process. The runtime expects that
- * execution will not resume after a fatal error. This is for "old-style" or legacy log handers.
+ * execution will not resume after a fatal error.
*/
void
mono_trace_set_log_handler (MonoLogCallback callback, void *user_data)
{
- g_assert (callback);
+ g_assert (callback);
+
if (logCallback.closer != NULL)
logCallback.closer();
- legacyLoggerUserData *ll = g_malloc (sizeof (legacyLoggerUserData));
+ UserSuppliedLoggerUserData *ll = g_malloc (sizeof (UserSuppliedLoggerUserData));
ll->legacy_callback = callback;
ll->user_data = user_data;
logCallback.opener = legacy_opener;
logCallback.closer = legacy_closer;
logCallback.user_data = ll;
logCallback.dest = NULL;
+
+ g_log_set_default_handler (eglib_log_adapter, user_data);
+}
+
+static void
+structured_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
+{
+ logCallback.writer (log_domain, log_level, logCallback.header, message);
}
/**
logCallback.closer = callback->closer;
logCallback.header = mono_trace_log_header;
logCallback.dest = callback->dest;
- logCallback.opener(logCallback.dest, user_data);
+ logCallback.opener (logCallback.dest, user_data);
+
+ g_log_set_default_handler (structured_log_adapter, user_data);
}
static void
MONO_API void
mono_trace_set_mask_string (const char *value);
-MONO_API void
-mono_trace_set_logdest_string (const char *value);
-
-MONO_API void
-mono_trace_set_logheader_string (const char *value);
-
typedef void (*MonoPrintCallback) (const char *string, mono_bool is_stdout);
typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data);
-
-typedef void (*MonoLoggerOpen) (const char *, void *);
-typedef void (*MonoLoggerWrite) (const char *, GLogLevelFlags, mono_bool, const char *, va_list);
-typedef void (*MonoLoggerClose) (void);
-
-typedef struct _MonoLogCallParm_ {
- MonoLoggerOpen opener; /* Routine to open logging */
- MonoLoggerWrite writer; /* Routine to write log data */
- MonoLoggerClose closer; /* Routine to close logging */
- char *dest; /* Log destination */
- void *user_data; /* User data from legacy handler */
- mono_bool header; /* Whether we want pid/time/date in log message */
-} MonoLogCallParm;
-
-void
-mono_trace_set_log_handler_internal (MonoLogCallParm *callback, void *user_data);
-
MONO_API void
mono_trace_set_log_handler (MonoLogCallback callback, void *user_data);
MONO_API void
mono_trace_set_printerr_handler (MonoPrintCallback callback);
-MONO_API void
-mono_log_open_syslog(const char *, void *);
-
-MONO_API void
-mono_log_write_syslog(const char *, GLogLevelFlags, mono_bool, const char *, va_list);
-
-MONO_API void
-mono_log_close_syslog(void);
-
-MONO_API void
-mono_log_open_logfile(const char *, void *);
-
-MONO_API void
-mono_log_write_logfile(const char *, GLogLevelFlags, mono_bool, const char *, va_list);
-
-MONO_API void
-mono_log_close_logfile(void);
-
MONO_END_DECLS
#endif /* __MONO_LOGGER_H__ */
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 ();
# define kinfo_starttime_member kp_proc.p_starttime
# define kinfo_pid_member kp_proc.p_pid
# define kinfo_name_member kp_proc.p_comm
+#elif defined(__NetBSD__)
+# define kinfo_starttime_member p_ustart_sec
+# define kinfo_pid_member p_pid
+# define kinfo_name_member p_comm
#elif defined(__OpenBSD__)
// Can not figure out how to get the proc's start time on OpenBSD
# undef kinfo_starttime_member
{
KINFO_PROC processi;
- if (sysctl_kinfo_proc (pid, &processi))
+ if (sysctl_kinfo_proc (pid, &processi)) {
+#if defined(__NetBSD__)
+ struct timeval tv;
+ tv.tv_sec = processi.kinfo_starttime_member;
+ tv.tv_usec = processi.p_ustart_usec;
+ *start_time = mono_100ns_datetime_from_timeval(tv);
+#else
*start_time = mono_100ns_datetime_from_timeval (processi.kinfo_starttime_member);
+#endif
+ }
}
#endif
get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoError *error)
{
struct sockaddr_un egd_addr;
- gint file;
+ gint socket_fd;
gint ret;
guint offset = 0;
int err = 0;
mono_error_init (error);
- file = socket (PF_UNIX, SOCK_STREAM, 0);
- if (file < 0) {
+ socket_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (socket_fd < 0) {
ret = -1;
err = errno;
} else {
egd_addr.sun_family = AF_UNIX;
strncpy (egd_addr.sun_path, path, sizeof (egd_addr.sun_path) - 1);
egd_addr.sun_path [sizeof (egd_addr.sun_path) - 1] = '\0';
- ret = connect (file, (struct sockaddr*) &egd_addr, sizeof (egd_addr));
+ ret = connect (socket_fd, (struct sockaddr*) &egd_addr, sizeof (egd_addr));
err = errno;
}
if (ret == -1) {
- if (file >= 0)
- close (file);
+ if (socket_fd >= 0)
+ close (socket_fd);
g_warning ("Entropy problem! Can't create or connect to egd socket %s", path);
mono_error_set_execution_engine (error, "Failed to open egd socket %s: %s", path, strerror (err));
return;
request [0] = 2;
request [1] = buffer_size < 255 ? buffer_size : 255;
while (count < 2) {
- int sent = write (file, request + count, 2 - count);
+ int sent = write (socket_fd, request + count, 2 - count);
err = errno;
if (sent >= 0) {
count += sent;
} else if (err == EINTR) {
continue;
} else {
- close (file);
+ close (socket_fd);
g_warning ("Send egd request failed %d", err);
mono_error_set_execution_engine (error, "Failed to send request to egd socket: %s", strerror (err));
return;
count = 0;
while (count != request [1]) {
int received;
- received = read (file, buffer + offset, request [1] - count);
+ received = read (socket_fd, buffer + offset, request [1] - count);
err = errno;
if (received > 0) {
count += received;
} else if (received < 0 && err == EINTR) {
continue;
} else {
- close (file);
+ close (socket_fd);
g_warning ("Receive egd request failed %d", err);
mono_error_set_execution_engine (error, "Failed to get response from egd socket: %s", strerror(err));
return;
buffer_size -= request [1];
}
- close (file);
+ close (socket_fd);
}
gboolean
void nacl_shutdown_gc_thread(void);
#endif
-typedef struct {
- pthread_t id;
- GPtrArray *owned_mutexes;
- gint32 priority;
-} MonoW32HandleThread;
-
-static gpointer
-thread_handle_create (void)
+void
+mono_threads_platform_register (MonoThreadInfo *info)
{
- MonoW32HandleThread thread_data;
gpointer thread_handle;
- thread_data.id = pthread_self ();
- thread_data.owned_mutexes = g_ptr_array_new ();
- thread_data.priority = MONO_THREAD_PRIORITY_NORMAL;
+ info->owned_mutexes = g_ptr_array_new ();
+ info->priority = MONO_THREAD_PRIORITY_NORMAL;
- thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, (gpointer) &thread_data);
+ thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, NULL);
if (thread_handle == INVALID_HANDLE_VALUE)
- return NULL;
+ g_error ("%s: failed to create handle", __func__);
/* We need to keep the handle alive, as long as the corresponding managed
* thread object is alive. The handle is going to be unref when calling
* the finalizer on the MonoThreadInternal object */
mono_w32handle_ref (thread_handle);
- return thread_handle;
-}
-
-static int
-win32_priority_to_posix_priority (MonoThreadPriority priority, int policy)
-{
- g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST);
- g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST);
-
-/* Necessary to get valid priority range */
-#ifdef _POSIX_PRIORITY_SCHEDULING
- int max, min;
-
- min = sched_get_priority_min (policy);
- max = sched_get_priority_max (policy);
-
- /* Partition priority range linearly (cross-multiply) */
- if (max > 0 && min >= 0 && max > min)
- return (int)((double) priority * (max - min) / (MONO_THREAD_PRIORITY_HIGHEST - MONO_THREAD_PRIORITY_LOWEST));
-#endif
-
- switch (policy) {
- case SCHED_FIFO:
- case SCHED_RR:
- return 50;
-#ifdef SCHED_BATCH
- case SCHED_BATCH:
-#endif
- case SCHED_OTHER:
- return 0;
- default:
- return -1;
- }
-}
-
-typedef struct {
- void *(*start_routine)(void*);
- void *arg;
- int flags;
- gint32 priority;
- MonoCoopSem registered;
- HANDLE handle;
-} StartInfo;
-
-static void*
-inner_start_thread (void *arg)
-{
- StartInfo *start_info = (StartInfo *) arg;
- void *t_arg = start_info->arg;
- int res;
- void *(*start_func)(void*) = start_info->start_routine;
- guint32 flags = start_info->flags;
- void *result;
- HANDLE handle;
- MonoThreadInfo *info;
-
- /* Register the thread with the io-layer */
- handle = thread_handle_create ();
- if (!handle) {
- mono_coop_sem_post (&(start_info->registered));
- return NULL;
- }
- start_info->handle = handle;
-
- info = mono_thread_info_attach (&result);
-
- info->runtime_thread = TRUE;
- info->handle = handle;
-
- mono_threads_platform_set_priority (info, start_info->priority);
-
- if (flags & CREATE_SUSPENDED) {
- info->create_suspended = TRUE;
- mono_coop_sem_init (&info->create_suspended_sem, 0);
- }
-
- /* start_info is not valid after this */
- mono_coop_sem_post (&(start_info->registered));
- start_info = NULL;
-
- if (flags & CREATE_SUSPENDED) {
- res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE);
- g_assert (res != -1);
-
- mono_coop_sem_destroy (&info->create_suspended_sem);
- }
-
- /* Run the actual main function of the thread */
- result = start_func (t_arg);
-
- mono_threads_platform_exit (GPOINTER_TO_UINT (result));
- g_assert_not_reached ();
+ g_assert (!info->handle);
+ info->handle = thread_handle;
}
-HANDLE
-mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
+int
+mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid)
{
pthread_attr_t attr;
- int res;
pthread_t thread;
- StartInfo start_info;
- guint32 stack_size;
- int policy;
- struct sched_param sp;
+ gint res;
res = pthread_attr_init (&attr);
g_assert (!res);
- if (tp->stack_size == 0) {
+#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+ if (stack_size == 0) {
#if HAVE_VALGRIND_MEMCHECK_H
if (RUNNING_ON_VALGRIND)
stack_size = 1 << 20;
#else
stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
#endif
- } else
- stack_size = tp->stack_size;
+ }
#ifdef PTHREAD_STACK_MIN
if (stack_size < PTHREAD_STACK_MIN)
stack_size = PTHREAD_STACK_MIN;
#endif
-#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
res = pthread_attr_setstacksize (&attr, stack_size);
g_assert (!res);
-#endif
-
- /*
- * For policies that respect priorities set the prirority for the new thread
- */
- pthread_getschedparam(pthread_self(), &policy, &sp);
- if ((policy == SCHED_FIFO) || (policy == SCHED_RR)) {
- sp.sched_priority = win32_priority_to_posix_priority (tp->priority, policy);
- res = pthread_attr_setschedparam (&attr, &sp);
- }
-
- memset (&start_info, 0, sizeof (StartInfo));
- start_info.start_routine = (void *(*)(void *)) start_routine;
- start_info.arg = arg;
- start_info.flags = tp->creation_flags;
- start_info.priority = tp->priority;
- mono_coop_sem_init (&(start_info.registered), 0);
+#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
/* Actually start the thread */
- res = mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info);
- if (res) {
- mono_coop_sem_destroy (&(start_info.registered));
- return NULL;
- }
-
- /* Wait until the thread register itself in various places */
- res = mono_coop_sem_wait (&start_info.registered, MONO_SEM_FLAGS_NONE);
- g_assert (res != -1);
-
- mono_coop_sem_destroy (&(start_info.registered));
+ res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data);
+ if (res)
+ return -1;
if (out_tid)
*out_tid = thread;
- return start_info.handle;
-}
-
-/*
- * mono_threads_platform_resume_created:
- *
- * Resume a newly created thread created using CREATE_SUSPENDED.
- */
-void
-mono_threads_platform_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid)
-{
- mono_coop_sem_post (&info->create_suspended_sem);
+ return 0;
}
gboolean
void
mono_threads_platform_exit (int exit_code)
{
- MonoThreadInfo *current = mono_thread_info_current ();
-
#if defined(__native_client__)
nacl_shutdown_gc_thread();
#endif
- mono_threads_platform_set_exited (current);
-
mono_thread_info_detach ();
pthread_exit (NULL);
void
mono_threads_platform_unregister (MonoThreadInfo *info)
{
- if (info->handle) {
- mono_threads_platform_set_exited (info);
- info->handle = NULL;
- }
-}
-
-HANDLE
-mono_threads_platform_open_handle (void)
-{
- MonoThreadInfo *info;
-
- info = mono_thread_info_current ();
- g_assert (info);
-
- if (!info->handle)
- info->handle = thread_handle_create ();
- else
- mono_w32handle_ref (info->handle);
- return info->handle;
+ mono_threads_platform_set_exited (info);
}
int
return handle;
}
+void
+mono_threads_platform_close_thread_handle (HANDLE handle)
+{
+ mono_w32handle_unref (handle);
+}
+
int
mono_threads_pthread_kill (MonoThreadInfo *info, int signum)
{
void
mono_threads_platform_set_exited (MonoThreadInfo *info)
{
- MonoW32HandleThread *thread_data;
gpointer mutex_handle;
int i, thr_ret;
pid_t pid;
pthread_t tid;
- if (!info->handle || mono_w32handle_issignalled (info->handle) || mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED) {
- /* We must have already deliberately finished
- * with this thread, so don't do any more now */
- return;
- }
+ g_assert (info->handle);
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer*) &thread_data))
- g_error ("unknown thread handle %p", info->handle);
+ if (mono_w32handle_issignalled (info->handle))
+ g_error ("%s: handle %p thread %p has already exited, it's handle is signalled", __func__, info->handle, mono_thread_info_get_tid (info));
+ if (mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED)
+ g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, info->handle, mono_thread_info_get_tid (info));
pid = wapi_getpid ();
tid = pthread_self ();
- for (i = 0; i < thread_data->owned_mutexes->len; i++) {
- mutex_handle = g_ptr_array_index (thread_data->owned_mutexes, i);
+ for (i = 0; i < info->owned_mutexes->len; i++) {
+ mutex_handle = g_ptr_array_index (info->owned_mutexes, i);
wapi_mutex_abandon (mutex_handle, pid, tid);
mono_thread_info_disown_mutex (info, mutex_handle);
}
- g_ptr_array_free (thread_data->owned_mutexes, TRUE);
+ g_ptr_array_free (info->owned_mutexes, TRUE);
thr_ret = mono_w32handle_lock_handle (info->handle);
g_assert (thr_ret == 0);
void
mono_threads_platform_describe (MonoThreadInfo *info, GString *text)
{
- MonoW32HandleThread *thread_data;
int i;
- g_assert (info->handle);
-
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer*) &thread_data))
- g_error ("unknown thread handle %p", info->handle);
-
g_string_append_printf (text, "thread handle %p state : ", info->handle);
mono_thread_info_describe_interrupt_token (info, text);
g_string_append_printf (text, ", owns (");
- for (i = 0; i < thread_data->owned_mutexes->len; i++)
- g_string_append_printf (text, i > 0 ? ", %p" : "%p", g_ptr_array_index (thread_data->owned_mutexes, i));
+ for (i = 0; i < info->owned_mutexes->len; i++)
+ g_string_append_printf (text, i > 0 ? ", %p" : "%p", g_ptr_array_index (info->owned_mutexes, i));
g_string_append_printf (text, ")");
}
void
mono_threads_platform_own_mutex (MonoThreadInfo *info, gpointer mutex_handle)
{
- MonoW32HandleThread *thread_data;
-
- g_assert (info->handle);
-
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer*) &thread_data))
- g_error ("unknown thread handle %p", info->handle);
-
mono_w32handle_ref (mutex_handle);
- g_ptr_array_add (thread_data->owned_mutexes, mutex_handle);
+ g_ptr_array_add (info->owned_mutexes, mutex_handle);
}
void
mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
{
- MonoW32HandleThread *thread_data;
-
- g_assert (info->handle);
-
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer*) &thread_data))
- g_error ("unknown thread handle %p", info->handle);
-
mono_w32handle_unref (mutex_handle);
- g_ptr_array_remove (thread_data->owned_mutexes, mutex_handle);
+ g_ptr_array_remove (info->owned_mutexes, mutex_handle);
}
MonoThreadPriority
mono_threads_platform_get_priority (MonoThreadInfo *info)
{
- MonoW32HandleThread *thread_data;
-
- g_assert (info->handle);
-
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer *)&thread_data))
- return MONO_THREAD_PRIORITY_NORMAL;
-
- return thread_data->priority;
+ return info->priority;
}
-gboolean
+void
mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
{
- MonoW32HandleThread *thread_data;
- int policy, posix_priority;
+ int policy;
struct sched_param param;
+ pthread_t tid;
+ gint res;
- g_assert (info->handle);
+ g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST);
+ g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST);
+ g_assert (MONO_THREAD_PRIORITY_LOWEST < MONO_THREAD_PRIORITY_HIGHEST);
- if (!mono_w32handle_lookup (info->handle, MONO_W32HANDLE_THREAD, (gpointer*) &thread_data))
- return FALSE;
-
- switch (pthread_getschedparam (thread_data->id, &policy, ¶m)) {
- case 0:
- break;
- case ESRCH:
- g_warning ("pthread_getschedparam: error looking up thread id %x", (gsize)thread_data->id);
- return FALSE;
- default:
- return FALSE;
- }
+ tid = mono_thread_info_get_tid (info);
- posix_priority = win32_priority_to_posix_priority (priority, policy);
- if (posix_priority < 0)
- return FALSE;
-
- param.sched_priority = posix_priority;
- switch (pthread_setschedparam (thread_data->id, policy, ¶m)) {
- case 0:
- break;
- case ESRCH:
- g_warning ("%s: pthread_setschedprio: error looking up thread id %x", __func__, (gsize)thread_data->id);
- return FALSE;
- case ENOTSUP:
- g_warning ("%s: priority %d not supported", __func__, priority);
- return FALSE;
- case EPERM:
- g_warning ("%s: permission denied", __func__);
- return FALSE;
- default:
- return FALSE;
- }
+ res = pthread_getschedparam (tid, &policy, ¶m);
+ if (res != 0)
+ g_error ("%s: pthread_getschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
- thread_data->priority = priority;
- return TRUE;
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ int max, min;
-}
+ /* Necessary to get valid priority range */
-static void thread_details (gpointer data)
-{
- MonoW32HandleThread *thread = (MonoW32HandleThread*) data;
- g_print ("id: %p, owned_mutexes: %d, priority: %d",
- thread->id, thread->owned_mutexes->len, thread->priority);
+ min = sched_get_priority_min (policy);
+ max = sched_get_priority_max (policy);
+
+ if (max > 0 && min >= 0 && max > min) {
+ double srange, drange, sposition, dposition;
+ srange = MONO_THREAD_PRIORITY_HIGHEST - MONO_THREAD_PRIORITY_LOWEST;
+ drange = max - min;
+ sposition = priority - MONO_THREAD_PRIORITY_LOWEST;
+ dposition = (sposition / srange) * drange;
+ param.sched_priority = (int)(dposition + min);
+ } else
+#endif
+ {
+ switch (policy) {
+ case SCHED_FIFO:
+ case SCHED_RR:
+ param.sched_priority = 50;
+ break;
+#ifdef SCHED_BATCH
+ case SCHED_BATCH:
+#endif
+ case SCHED_OTHER:
+ param.sched_priority = 0;
+ break;
+ default:
+ g_error ("%s: unknown policy %d", __func__, policy);
+ }
+ }
+
+ res = pthread_setschedparam (tid, policy, ¶m);
+ if (res != 0) {
+ if (res == EPERM) {
+ g_warning ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
+ return;
+ }
+ g_error ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
+ }
+
+ info->priority = priority;
}
static const gchar* thread_typename (void)
static gsize thread_typesize (void)
{
- return sizeof (MonoW32HandleThread);
+ return 0;
}
static MonoW32HandleOps thread_ops = {
NULL, /* is_owned */
NULL, /* special_wait */
NULL, /* prewait */
- thread_details, /* details */
+ NULL, /* details */
thread_typename, /* typename */
thread_typesize, /* typesize */
};
#if defined (PLATFORM_ANDROID)
info->native_handle = gettid ();
#endif
-
- g_assert (!info->handle);
- info->handle = thread_handle_create ();
}
void
void
mono_threads_suspend_register (MonoThreadInfo *info)
{
- g_assert (!info->handle);
- info->handle = mono_threads_platform_open_handle();
}
void
#if defined (HOST_WIN32)
-typedef struct {
- LPTHREAD_START_ROUTINE start_routine;
- void *arg;
- gint32 priority;
- MonoCoopSem registered;
- gboolean suspend;
- HANDLE suspend_event;
-} ThreadStartInfo;
-
-static DWORD WINAPI
-inner_start_thread (LPVOID arg)
+void
+mono_threads_platform_register (MonoThreadInfo *info)
{
- ThreadStartInfo *start_info = arg;
- void *t_arg = start_info->arg;
- int post_result;
- LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
- DWORD result;
- gboolean suspend = start_info->suspend;
- HANDLE suspend_event = start_info->suspend_event;
- MonoThreadInfo *info;
-
- info = mono_thread_info_attach (&result);
- info->runtime_thread = TRUE;
- info->create_suspended = suspend;
-
- mono_threads_platform_set_priority(info, start_info->priority);
-
- mono_coop_sem_post (&(start_info->registered));
-
- if (suspend) {
- WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
- CloseHandle (suspend_event);
- }
+ HANDLE thread_handle;
- result = start_func (t_arg);
+ thread_handle = GetCurrentThread ();
+ g_assert (thread_handle);
- mono_thread_info_detach ();
+ /* The handle returned by GetCurrentThread () is a pseudo handle, so it can't
+ * be used to refer to the thread from other threads for things like aborting. */
+ DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0);
- return result;
+ g_assert (!info->handle);
+ info->handle = thread_handle;
}
-HANDLE
-mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
+int
+mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid)
{
- ThreadStartInfo *start_info;
HANDLE result;
DWORD thread_id;
- guint32 creation_flags = tp->creation_flags;
- int res;
-
- start_info = g_malloc0 (sizeof (ThreadStartInfo));
- if (!start_info)
- return NULL;
- mono_coop_sem_init (&(start_info->registered), 0);
- start_info->arg = arg;
- start_info->priority = tp->priority;
- start_info->start_routine = start_routine;
- start_info->suspend = creation_flags & CREATE_SUSPENDED;
- creation_flags &= ~CREATE_SUSPENDED;
- if (start_info->suspend) {
- start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
- if (!start_info->suspend_event)
- return NULL;
- }
- result = CreateThread (NULL, tp->stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
- if (result) {
- res = mono_coop_sem_wait (&(start_info->registered), MONO_SEM_FLAGS_NONE);
- g_assert (res != -1);
+ result = CreateThread (NULL, stack_size, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id);
+ if (!result)
+ return -1;
+
+ /* A new handle is open when attaching
+ * the thread, so we don't need this one */
+ CloseHandle (result);
- if (start_info->suspend) {
- g_assert (SuspendThread (result) != (DWORD)-1);
- SetEvent (start_info->suspend_event);
- }
- } else if (start_info->suspend) {
- CloseHandle (start_info->suspend_event);
- }
if (out_tid)
*out_tid = thread_id;
- mono_coop_sem_destroy (&(start_info->registered));
- g_free (start_info);
- return result;
+
+ return 0;
}
return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL;
}
-void
-mono_threads_platform_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid)
-{
- HANDLE handle;
-
- handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid);
- g_assert (handle);
- ResumeThread (handle);
- CloseHandle (handle);
-}
-
#if HAVE_DECL___READFSDWORD==0
static MONO_ALWAYS_INLINE unsigned long long
__readfsdword (unsigned long offset)
void
mono_threads_platform_exit (int exit_code)
{
+ mono_thread_info_detach ();
ExitThread (exit_code);
}
void
mono_threads_platform_unregister (MonoThreadInfo *info)
{
-}
-
-HANDLE
-mono_threads_platform_open_handle (void)
-{
- HANDLE thread_handle;
-
- thread_handle = GetCurrentThread ();
- g_assert (thread_handle);
-
- /*
- * The handle returned by GetCurrentThread () is a pseudo handle, so it can't be used to
- * refer to the thread from other threads for things like aborting.
- */
- DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle,
- THREAD_ALL_ACCESS, TRUE, 0);
-
- return thread_handle;
+ mono_threads_platform_set_exited (info);
}
int
return OpenThread (THREAD_ALL_ACCESS, TRUE, tid);
}
+void
+mono_threads_platform_close_thread_handle (HANDLE handle)
+{
+ CloseHandle (handle);
+}
+
#if defined(_MSC_VER)
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
void
mono_threads_platform_set_exited (MonoThreadInfo *info)
{
+ g_assert (info->handle);
+ // No need to call CloseHandle() here since the InternalThread
+ // destructor will close the handle when the finalizer thread calls it
+ info->handle = NULL;
}
void
return GetThreadPriority (info->handle) + 2;
}
-gboolean
+void
mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
{
+ BOOL res;
+
g_assert (info->handle);
- return SetThreadPriority (info->handle, priority - 2);
+
+ res = SetThreadPriority (info->handle, priority - 2);
+ if (!res)
+ g_error ("%s: SetThreadPriority failed, error %d", __func__, GetLastError ());
}
void
MonoThreadInfo*
mono_thread_info_lookup (MonoNativeThreadId id)
{
- MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+ 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;
}
{
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;
}
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;
}
info->stackdata = g_byte_array_new ();
+ mono_threads_platform_register (info);
mono_threads_suspend_register (info);
/*
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_platform_init ();
mono_threads_suspend_init ();
mono_thread_info_core_resume (MonoThreadInfo *info)
{
gboolean res = FALSE;
- if (info->create_suspended) {
- MonoNativeThreadId tid = mono_thread_info_get_tid (info);
- /* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
- info->create_suspended = FALSE;
- mono_threads_platform_resume_created (info, tid);
- return TRUE;
- }
switch (mono_threads_transition_request_resume (info)) {
case ResumeError:
return FALSE;
}
+typedef struct {
+ gint32 ref;
+ MonoThreadStart start_routine;
+ gpointer start_routine_arg;
+ gint32 priority;
+ MonoCoopSem registered;
+ MonoThreadInfo *info;
+} CreateThreadData;
+
+static gsize WINAPI
+inner_start_thread (gpointer data)
+{
+ CreateThreadData *thread_data;
+ MonoThreadInfo *info;
+ MonoThreadStart start_routine;
+ gpointer start_routine_arg;
+ guint32 start_routine_res;
+ gint32 priority;
+ gsize dummy;
+
+ thread_data = (CreateThreadData*) data;
+ g_assert (thread_data);
+
+ start_routine = thread_data->start_routine;
+ start_routine_arg = thread_data->start_routine_arg;
+
+ priority = thread_data->priority;
+
+ info = mono_thread_info_attach (&dummy);
+ info->runtime_thread = TRUE;
+
+ mono_threads_platform_set_priority (info, priority);
+
+ thread_data->info = info;
+
+ mono_coop_sem_post (&thread_data->registered);
+
+ if (InterlockedDecrement (&thread_data->ref) == 0) {
+ mono_coop_sem_destroy (&thread_data->registered);
+ g_free (thread_data);
+ }
+
+ /* thread_data is not valid anymore */
+ thread_data = NULL;
+
+ /* Run the actual main function of the thread */
+ start_routine_res = start_routine (start_routine_arg);
+
+ mono_threads_platform_exit (start_routine_res);
+
+ g_assert_not_reached ();
+}
+
/*
* mono_threads_create_thread:
*
HANDLE
mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
{
- return mono_threads_platform_create_thread (start, arg, tp, out_tid);
+ CreateThreadData *thread_data;
+ MonoThreadInfo *info;
+ gint res;
+ gpointer ret;
+
+ thread_data = g_new0 (CreateThreadData, 1);
+ thread_data->ref = 2;
+ thread_data->start_routine = start;
+ thread_data->start_routine_arg = arg;
+ thread_data->priority = tp->priority;
+ mono_coop_sem_init (&thread_data->registered, 0);
+
+ res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, tp->stack_size, out_tid);
+ if (res != 0) {
+ /* ref is not going to be decremented in inner_start_thread */
+ InterlockedDecrement (&thread_data->ref);
+ ret = NULL;
+ goto done;
+ }
+
+ res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE);
+ g_assert (res == 0);
+
+ info = thread_data->info;
+ g_assert (info);
+
+ ret = info->handle;
+ g_assert (ret);
+
+done:
+ if (InterlockedDecrement (&thread_data->ref) == 0) {
+ mono_coop_sem_destroy (&thread_data->registered);
+ g_free (thread_data);
+ }
+
+ return ret;
}
/*
mono_threads_platform_exit (0);
}
-/*
- * mono_thread_info_open_handle:
- *
- * Return a io-layer/win32 handle for the current thread.
- * The handle need to be closed by calling CloseHandle () when it is no
- * longer needed.
- */
-HANDLE
-mono_thread_info_open_handle (void)
-{
- return mono_threads_platform_open_handle ();
-}
-
/*
* mono_threads_open_thread_handle:
*
return mono_threads_platform_open_thread_handle (handle, tid);
}
+void
+mono_threads_close_thread_handle (HANDLE handle)
+{
+ return mono_threads_platform_close_thread_handle (handle);
+}
+
#define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1)
struct _MonoThreadInfoInterruptToken {
return mono_threads_platform_get_priority (info);
}
-gboolean
+void
mono_thread_info_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
{
- return mono_threads_platform_set_priority (info, priority);
+ mono_threads_platform_set_priority (info, priority);
}
*/
gboolean is_async_context;
- gboolean create_suspended;
-
- /* Semaphore used to implement CREATE_SUSPENDED */
- MonoCoopSem create_suspended_sem;
-
/*
* Values of TLS variables for this thread.
* This can be used to obtain the values of TLS variable for threads
/* Stack mark for targets that explicitly require one */
gpointer stack_mark;
+
+#if defined(_POSIX_VERSION) || defined(__native_client__)
+ /* This is the data that was stored in the w32 handle */
+ GPtrArray *owned_mutexes;
+ gint32 priority;
+#endif
} MonoThreadInfo;
typedef struct {
void
mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize);
-gboolean
+MONO_API gboolean
mono_thread_info_yield (void);
gint
void
mono_thread_info_exit (void);
-HANDLE
-mono_thread_info_open_handle (void);
-
void
mono_thread_info_set_exited (THREAD_INFO_TYPE *info);
HANDLE
mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
+void
+mono_threads_close_thread_handle (HANDLE handle);
+
MONO_API void
mono_threads_attach_tools_thread (void);
void mono_threads_suspend_abort_syscall (THREAD_INFO_TYPE *info);
gboolean mono_threads_suspend_needs_abort_syscall (void);
-HANDLE mono_threads_platform_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *, MonoNativeThreadId *out_tid);
-void mono_threads_platform_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid);
+void mono_threads_platform_register (THREAD_INFO_TYPE *info);
+void mono_threads_platform_unregister (THREAD_INFO_TYPE *info);
+int mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid);
void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize);
gboolean mono_threads_platform_yield (void);
void mono_threads_platform_exit (int exit_code);
-void mono_threads_platform_unregister (THREAD_INFO_TYPE *info);
-HANDLE mono_threads_platform_open_handle (void);
HANDLE mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
+void mono_threads_platform_close_thread_handle (HANDLE handle);
void mono_threads_platform_set_exited (THREAD_INFO_TYPE *info);
void mono_threads_platform_describe (THREAD_INFO_TYPE *info, GString *text);
void mono_threads_platform_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
void mono_threads_platform_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
MonoThreadPriority mono_threads_platform_get_priority (THREAD_INFO_TYPE *info);
-gboolean mono_threads_platform_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
+void mono_threads_platform_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
void mono_threads_coop_begin_global_suspend (void);
void mono_threads_coop_end_global_suspend (void);
MonoThreadPriority
mono_thread_info_get_priority (THREAD_INFO_TYPE *info);
-gboolean
+void
mono_thread_info_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
#endif /* __MONO_THREADS_H__ */
#include "mono-os-mutex.h"
#include "mono-proclib.h"
#include "mono-threads.h"
+#include "mono-time.h"
#undef DEBUG_REFS
/* must be a power of 2 */
#define HANDLE_PER_SLOT (256)
+#define INFINITE 0xFFFFFFFF
+
typedef struct {
MonoW32HandleType type;
guint ref;
return handle_data->signalled;
}
-int
+static int
mono_w32handle_lock_signal_mutex (void)
{
#ifdef DEBUG
return 0;
}
-int
+static int
mono_w32handle_unlock_signal_mutex (void)
{
#ifdef DEBUG
void
mono_w32handle_init (void)
{
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
== MONO_W32HANDLE_COUNT);
mono_os_cond_init (&global_signal_cond);
mono_os_mutex_init (&global_signal_mutex);
+
+ initialized = TRUE;
}
static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
MonoW32HandleType type, gpointer handle_specific)
{
- g_assert (!shutting_down);
-
handle->type = type;
handle->signalled = FALSE;
handle->ref = 1;
static guint32 last = 0;
gboolean retry = FALSE;
- g_assert (!shutting_down);
-
/* A linear scan should be fast enough. Start from the last
* allocation, assuming that handles are allocated more often
* than they're freed. Leave the space reserved for file
nanosleep (&sleepytime, NULL);
}
-gboolean
-mono_w32handle_count_signalled_handles (guint32 numhandles, gpointer *handles,
- gboolean waitall, guint32 *retcount, guint32 *lowest)
+static void
+mono_w32handle_lock_handles (gpointer *handles, gsize numhandles)
{
- guint32 count, i, iter=0;
- gboolean ret;
+ guint32 i, iter=0;
int thr_ret;
/* Lock all the handles, with backoff */
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Locked all handles", __func__);
-
- count=0;
- *lowest=numhandles;
-
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Checking handle %p", __func__, handle);
-
- if(((mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)==TRUE) &&
- (mono_w32handle_ops_isowned (handle) == TRUE)) ||
- (mono_w32handle_issignalled (handle))) {
- count++;
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Handle %p signalled", __func__,
- handle);
- if(*lowest>i) {
- *lowest=i;
- }
- }
- }
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: %d event handles signalled", __func__, count);
-
- if ((waitall == TRUE && count == numhandles) ||
- (waitall == FALSE && count > 0)) {
- ret=TRUE;
- } else {
- ret=FALSE;
- }
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Returning %d", __func__, ret);
-
- *retcount=count;
-
- return(ret);
}
-void mono_w32handle_unlock_handles (guint32 numhandles, gpointer *handles)
+static void
+mono_w32handle_unlock_handles (gpointer *handles, gsize numhandles)
{
guint32 i;
int thr_ret;
mono_os_mutex_unlock (&global_signal_mutex);
}
-int
+static int
mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
{
int res;
mono_w32handle_unref (handle);
}
-int
+static int
mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
{
MonoW32HandleBase *handle_data;
mono_os_mutex_unlock (&scan_mutex);
}
+static gboolean
+own_if_signalled (gpointer handle)
+{
+ if (!mono_w32handle_issignalled (handle))
+ return FALSE;
+
+ mono_w32handle_ops_own (handle);
+ return TRUE;
+}
+
+static gboolean
+own_if_owned( gpointer handle)
+{
+ if (!mono_w32handle_ops_isowned (handle))
+ return FALSE;
+
+ mono_w32handle_ops_own (handle);
+ return TRUE;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gboolean alerted;
+ gint64 start;
+ gint thr_ret;
+
+ alerted = FALSE;
+
+ if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p has special wait",
+ __func__, handle);
+
+ switch (mono_w32handle_ops_specialwait (handle, timeout, alertable ? &alerted : NULL)) {
+ case WAIT_OBJECT_0:
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ break;
+ case WAIT_IO_COMPLETION:
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ break;
+ case WAIT_TIMEOUT:
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ break;
+ case WAIT_FAILED:
+ ret = MONO_W32HANDLE_WAIT_RET_FAILED;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (alerted)
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+
+ return ret;
+ }
+
+ if (!mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_WAIT)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
+ __func__, handle);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)) {
+ if (own_if_owned (handle)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
+ __func__, handle);
+
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (;;) {
+ gint waited;
+
+ if (own_if_signalled (handle)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
+ __func__, handle);
+
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+
+ mono_w32handle_ops_prewait (handle);
+
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal_handle (handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
+ }
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gboolean alerted, poll;
+ gint i, thr_ret;
+ gint64 start;
+ gpointer handles_sorted [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
+
+ if (nhandles == 0)
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+
+ if (nhandles == 1)
+ return mono_w32handle_wait_one (handles [0], timeout, alertable);
+
+ alerted = FALSE;
+
+ if (nhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: too many handles: %d",
+ __func__, nhandles);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ for (i = 0; i < nhandles; ++i) {
+ if (!mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT)
+ && !mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT))
+ {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
+ __func__, handles [i]);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ handles_sorted [i] = handles [i];
+ }
+
+ qsort (handles_sorted, nhandles, sizeof (gpointer), g_direct_equal);
+ for (i = 1; i < nhandles; ++i) {
+ if (handles_sorted [i - 1] == handles_sorted [i]) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p is duplicated",
+ __func__, handles_sorted [i]);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+ }
+
+ poll = FALSE;
+ for (i = 0; i < nhandles; ++i) {
+ if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS) {
+ /* Can't wait for a process handle + another handle without polling */
+ poll = TRUE;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (i = 0; i < nhandles; ++i) {
+ /* Add a reference, as we need to ensure the handle wont
+ * disappear from under us while we're waiting in the loop
+ * (not lock, as we don't want exclusive access here) */
+ mono_w32handle_ref (handles [i]);
+ }
+
+ for (;;) {
+ gsize count, lowest;
+ gboolean signalled;
+ gint waited;
+
+ count = 0;
+ lowest = nhandles;
+
+ mono_w32handle_lock_handles (handles, nhandles);
+
+ for (i = 0; i < nhandles; i++) {
+ if ((mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_OWN) && mono_w32handle_ops_isowned (handles [i]))
+ || mono_w32handle_issignalled (handles [i]))
+ {
+ count ++;
+
+ if (i < lowest)
+ lowest = i;
+ }
+ }
+
+ signalled = (waitall && count == nhandles) || (!waitall && count > 0);
+
+ if (signalled) {
+ for (i = 0; i < nhandles; i++)
+ own_if_signalled (handles [i]);
+ }
+
+ mono_w32handle_unlock_handles (handles, nhandles);
+
+ if (signalled) {
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + lowest;
+ goto done;
+ }
+
+ for (i = 0; i < nhandles; i++) {
+ mono_w32handle_ops_prewait (handles[i]);
+
+ if (mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_SPECIAL_WAIT)
+ && !mono_w32handle_issignalled (handles [i]))
+ {
+ mono_w32handle_ops_specialwait (handles [i], 0, alertable ? &alerted : NULL);
+ }
+ }
+
+ thr_ret = mono_w32handle_lock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ if (waitall) {
+ signalled = TRUE;
+ for (i = 0; i < nhandles; ++i) {
+ if (!mono_w32handle_issignalled (handles [i])) {
+ signalled = FALSE;
+ break;
+ }
+ }
+ } else {
+ signalled = FALSE;
+ for (i = 0; i < nhandles; ++i) {
+ if (mono_w32handle_issignalled (handles [i])) {
+ signalled = TRUE;
+ break;
+ }
+ }
+ }
+
+ waited = 0;
+
+ if (!signalled) {
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal (INFINITE, poll, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+
+ thr_ret = mono_w32handle_unlock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal (timeout - elapsed, poll, alertable ? &alerted : NULL);
+ }
+ }
+
+ thr_ret = mono_w32handle_unlock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ for (i = 0; i < nhandles; i++) {
+ /* Unref everything we reffed above */
+ mono_w32handle_unref (handles [i]);
+ }
+
+ return ret;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gint64 start;
+ gboolean alerted;
+ gint thr_ret;
+
+ alerted = FALSE;
+
+ if (!mono_w32handle_test_capabilities (signal_handle, MONO_W32HANDLE_CAP_SIGNAL))
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ if (!mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_WAIT))
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+
+ if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
+ g_warning ("%s: handle %p has special wait, implement me!!", __func__, wait_handle);
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (wait_handle);
+ g_assert (thr_ret == 0);
+
+ mono_w32handle_ops_signal (signal_handle);
+
+ if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_OWN)) {
+ if (own_if_owned (wait_handle)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
+ __func__, wait_handle);
+
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (;;) {
+ gint waited;
+
+ if (own_if_signalled (wait_handle)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
+ __func__, wait_handle);
+
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+
+ mono_w32handle_ops_prewait (wait_handle);
+
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal_handle (wait_handle, INFINITE, FALSE, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal_handle (wait_handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
+ }
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ thr_ret = mono_w32handle_unlock_handle (wait_handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
#endif /* !defined(HOST_WIN32) */
#define _MONO_UTILS_W32HANDLE_H_
#include <config.h>
-
-#if !defined(HOST_WIN32)
-
#include <glib.h>
+#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE (gpointer)-1
+#endif
+
+#define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64
typedef enum {
MONO_W32HANDLE_UNUSED = 0,
gsize
mono_w32handle_ops_typesize (MonoW32HandleType type);
-gboolean
-mono_w32handle_count_signalled_handles (guint32 numhandles, gpointer *handles, gboolean waitall, guint32 *retcount, guint32 *lowest);
-
-void
-mono_w32handle_unlock_handles (guint32 numhandles, gpointer *handles);
-
-int
-mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted);
-
-int
-mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted);
-
void
mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
int
mono_w32handle_unlock_handle (gpointer handle);
-int
-mono_w32handle_lock_signal_mutex (void);
+typedef enum {
+ MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0,
+ MONO_W32HANDLE_WAIT_RET_ALERTED = -1,
+ MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2,
+ MONO_W32HANDLE_WAIT_RET_FAILED = -3,
+} MonoW32HandleWaitRet;
-int
-mono_w32handle_unlock_signal_mutex (void);
+MonoW32HandleWaitRet
+mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable);
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable);
-#endif /* !defined(HOST_WIN32) */
+MonoW32HandleWaitRet
+mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable);
#endif /* _MONO_UTILS_W32HANDLE_H_ */
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\mono\sgen\sgen-alloc.c" />\r
- <ClCompile Include="..\mono\metadata\sgen-bridge.c" />\r
<ClCompile Include="..\mono\sgen\sgen-array-list.c" />\r
<ClCompile Include="..\mono\sgen\sgen-cardtable.c" />\r
<ClCompile Include="..\mono\sgen\sgen-debug.c" />\r
<ClCompile Include="..\mono\sgen\sgen-alloc.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\sgen-bridge.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\mono\sgen\sgen-cardtable.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
</ProjectConfiguration>\r
</ItemGroup>\r
<ItemGroup>\r
- <ClCompile Include="..\mono\metadata\remoting.c" />\r
<ClCompile Include="..\mono\mini\alias-analysis.c" />\r
<ClCompile Include="..\mono\mini\arch-stubs.c" />\r
<ClCompile Include="..\mono\mini\exceptions-amd64.c">\r
<ClCompile Include="..\mono\mini\mini-x86.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\remoting.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\mono\mini\seq-points.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<LinkLibraryDependencies>true</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmono-static$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<ModuleDefinitionFile>$(MONO_DEF)</ModuleDefinitionFile>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<LinkLibraryDependencies>true</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmono-static$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<ModuleDefinitionFile>$(MONO_DEF)</ModuleDefinitionFile>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<LinkLibraryDependencies>true</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmono-static$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<ModuleDefinitionFile>$(MONO_DEF)</ModuleDefinitionFile>\r
<RandomizedBaseAddress>false</RandomizedBaseAddress>\r
<LinkLibraryDependencies>true</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmono-static$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<ModuleDefinitionFile>$(MONO_DEF)</ModuleDefinitionFile>\r
<ImportLibrary>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib</ImportLibrary>\r
<Project>{8fc2b0c8-51ad-49df-851f-5d01a77a75e4}</Project>\r
</ProjectReference>\r
</ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="..\mono\mini\mini-windows-dllmain.c" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="mono.def" />\r
+ </ItemGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
<ImportGroup Label="ExtensionTargets">\r
</ImportGroup>\r
<UniqueIdentifier>{5370c3c4-b6ec-4f8a-8b21-ce4e782720a6}</UniqueIdentifier>\r
</Filter>\r
</ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="..\mono\mini\mini-windows-dllmain.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="mono.def">\r
+ <Filter>Resource Files</Filter>\r
+ </None>\r
+ </ItemGroup>\r
</Project>
\ No newline at end of file
<ClCompile Include="..\mono\metadata\cominterop.c" />\r
<ClCompile Include="..\mono\metadata\console-win32.c" />\r
<ClCompile Include="..\mono\metadata\coree.c" />\r
+ <ClCompile Include="..\mono\metadata\custom-attrs.c" />\r
<ClCompile Include="..\mono\metadata\debug-helpers.c" />\r
<ClCompile Include="..\mono\metadata\debug-mono-ppdb.c" />\r
<ClCompile Include="..\mono\metadata\debug-mono-symfile.c" />\r
<ClCompile Include="..\mono\metadata\decimal-ms.c" />\r
+ <ClCompile Include="..\mono\metadata\dynamic-image.c" />\r
+ <ClCompile Include="..\mono\metadata\dynamic-stream.c" />\r
<ClCompile Include="..\mono\metadata\domain.c" />\r
<ClCompile Include="..\mono\metadata\environment.c" />\r
<ClCompile Include="..\mono\metadata\exception.c" />\r
<ClCompile Include="..\mono\metadata\mono-security.c" />\r
<ClCompile Include="..\mono\metadata\seq-points-data.c" />\r
<ClCompile Include="..\mono\metadata\sgen-mono.c" />\r
+ <ClCompile Include="..\mono\metadata\sgen-os-coop.c" />\r
<ClCompile Include="..\mono\metadata\threadpool-ms-io.c" />\r
<ClCompile Include="..\mono\metadata\threadpool-ms.c" />\r
<ClCompile Include="..\mono\metadata\sgen-bridge.c" />\r
<ClCompile Include="..\mono\metadata\sgen-toggleref.c" />\r
<ClCompile Include="..\mono\metadata\sgen-stw.c" />\r
<ClCompile Include="..\mono\metadata\socket-io.c" />\r
+ <ClCompile Include="..\mono\metadata\sre.c" />\r
+ <ClCompile Include="..\mono\metadata\sre-encode.c" />\r
+ <ClCompile Include="..\mono\metadata\sre-save.c" />\r
<ClCompile Include="..\mono\metadata\string-icalls.c" />\r
<ClCompile Include="..\mono\metadata\sysmath.c" />\r
<ClCompile Include="..\mono\metadata\threads.c" />\r
<ClInclude Include="..\mono\metadata\coree.h" />\r
<ClInclude Include="..\mono\metadata\culture-info-tables.h" />\r
<ClInclude Include="..\mono\metadata\culture-info.h" />\r
+ <ClInclude Include="..\mono\metadata\custom-attrs-internals.h" />\r
<ClInclude Include="..\mono\metadata\debug-helpers.h" />\r
<ClInclude Include="..\mono\metadata\debug-mono-ppdb.h" />\r
<ClInclude Include="..\mono\metadata\debug-mono-symfile.h" />\r
<ClInclude Include="..\mono\metadata\domain-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\dynamic-image-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\dynamic-stream-internals.h" />\r
<ClInclude Include="..\mono\metadata\environment.h" />\r
<ClInclude Include="..\mono\metadata\exception.h" />\r
<ClInclude Include="..\mono\metadata\file-io.h" />\r
<ClInclude Include="..\mono\metadata\profiler.h" />\r
<ClInclude Include="..\mono\metadata\rand.h" />\r
<ClInclude Include="..\mono\metadata\reflection.h" />\r
+ <ClInclude Include="..\mono\metadata\reflection-cache.h" />\r
+ <ClInclude Include="..\mono\metadata\reflection-internals.h" />\r
<ClInclude Include="..\mono\metadata\runtime.h" />\r
<ClInclude Include="..\mono\metadata\security-core-clr.h" />\r
<ClInclude Include="..\mono\metadata\security-manager.h" />\r
<ClInclude Include="..\mono\metadata\sgen-bridge.h" />\r
<ClInclude Include="..\mono\metadata\sgen-toggleref.h" />\r
<ClInclude Include="..\mono\metadata\socket-io.h" />\r
+ <ClInclude Include="..\mono\metadata\sre-internals.h" />\r
<ClInclude Include="..\mono\metadata\string-icalls.h" />\r
<ClInclude Include="..\mono\metadata\sysmath.h" />\r
<ClInclude Include="..\mono\metadata\tabledefs.h" />\r
<ClCompile Include="..\mono\metadata\metadata-cross-helpers.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\mono\metadata\custom-attrs.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\dynamic-image.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\dynamic-stream.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\sre.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\sre-encode.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\sre-save.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\sgen-os-coop.c">\r
+ <Filter>Source Files\sgen</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="..\mono\metadata\appdomain.h">\r
<ClInclude Include="..\mono\metadata\gc-internals.h">\r
<Filter>Header Files\gc</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\mono\metadata\custom-attrs-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\dynamic-image-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\dynamic-stream-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\reflection-cache.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\reflection-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\sre-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="Header Files">\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
<PlatformToolset>v140</PlatformToolset>\r
</PropertyGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
</ImportGroup>\r
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
- <Import Project="mono.props" />\r
+ <Import Project="mono.props" />\r
<Import Project="mono-test.props" />\r
<Import Project="mono-test-x64.props" />\r
<Import Project="mono-full-aot-test.props" />\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
<PlatformToolset>v140</PlatformToolset>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<PlatformToolset>v140</PlatformToolset>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
<PlatformToolset>v140</PlatformToolset>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
<ConfigurationType>Utility</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<PlatformToolset>v140</PlatformToolset>\r
<WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>Unicode</CharacterSet>\r
</PropertyGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
<ImportGroup Label="ExtensionSettings">\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="UserMacros">
+ <MONO_NUNIT_TEST_DIR>$(MONO_DIR)/mcs/class/System</MONO_NUNIT_TEST_DIR>
+ <MONO_NUNIT_TARGET>$(MONO_DIR)/mcs/class/lib/net_4_x/nunit-console.exe</MONO_NUNIT_TARGET>
+ <MONO_PATH>$(MONO_PATH);$(MONO_NUNIT_TEST_DIR)</MONO_PATH>
+ <MONO_CFG_DIR>$(MONO_DIR)/runtime/etc</MONO_CFG_DIR>
+ <MONO_NUNIT_RUN_TARGET>net_4_x_System_test.dll</MONO_NUNIT_RUN_TARGET>
+ <MONO_NUNIT_FIXTURE></MONO_NUNIT_FIXTURE>
+ <MONO_NUNIT_ARGS>-noshadow -exclude=NotWorking,ValueAdd,CAS,InetAccess /labels</MONO_NUNIT_ARGS>
+ <MONO_NUNIT_ARGS Condition="'$(MONO_NUNIT_FIXTURE)'!=''">$(MONO_NUNIT_ARGS) -fixture $(MONO_NUNIT_FIXTURE)</MONO_NUNIT_ARGS>
+ <MONO_NUNIT_RUN_ADDITIONAL_ARGS>
+ </MONO_NUNIT_RUN_ADDITIONAL_ARGS>
+ <MONO_NUNIT_RUN_ARGS>"$(MONO_NUNIT_TARGET)" "$(MONO_NUNIT_RUN_TARGET)" $(MONO_NUNIT_ARGS) $(MONO_NUNIT_RUN_ADDITIONAL_ARGS)</MONO_NUNIT_RUN_ARGS>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="MONO_NUNIT_TEST_DIR">
+ <Value>$(MONO_NUNIT_TEST_DIR)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_TARGET">
+ <Value>$(MONO_NUNIT_TARGET)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_PATH">
+ <Value>$(MONO_PATH)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_CFG_DIR">
+ <Value>$(MONO_CFG_DIR)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_RUN_TARGET">
+ <Value>$(MONO_NUNIT_RUN_TARGET)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_FIXTURE">
+ <Value>$(MONO_NUNIT_FIXTURE)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_ARGS">
+ <Value>$(MONO_NUNIT_ARGS)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_RUN_ADDITIONAL_ARGS">
+ <Value>$(MONO_NUNIT_RUN_ADDITIONAL_ARGS)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_NUNIT_RUN_ARGS">
+ <Value>$(MONO_NUNIT_RUN_ARGS)</Value>
+ </BuildMacro>
+ </ItemGroup>
+ <ItemDefinitionGroup />
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup Label="ProjectConfigurations">\r
+ <ProjectConfiguration Include="Debug|Win32">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|Win32">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|x64">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|x64">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ProjectReference Include="mono.vcxproj">\r
+ <Project>{a0eddcd9-940f-432c-a28f-7ef322437d79}</Project>\r
+ </ProjectReference>\r
+ </ItemGroup>\r
+ <PropertyGroup Label="Globals">\r
+ <ProjectGuid>{0046B994-40A8-4C64-AC9D-429DC9177B54}</ProjectGuid>\r
+ <Keyword>Win32Proj</Keyword>\r
+ <RootNamespace>mononunittest</RootNamespace>\r
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+ <ImportGroup Label="ExtensionSettings">\r
+ </ImportGroup>\r
+ <ImportGroup Label="Shared">\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-Win32.props" />\r
+ <Import Project="mono-nunit-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-Win32.props" />\r
+ <Import Project="mono-nunit-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-x64.props" />\r
+ <Import Project="mono-nunit-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-x64.props" />\r
+ <Import Project="mono-nunit-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <PropertyGroup Label="UserMacros" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <LocalDebuggerCommandArguments>$(MONO_NUNIT_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_NUNIT_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_NUNIT_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_NUNIT_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_NUNIT_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_NUNIT_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_NUNIT_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_NUNIT_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <PreBuildEvent>\r
+ <Command>\r
+ </Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <PreBuildEvent>\r
+ <Command>\r
+ </Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <Link>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ <PreBuildEvent>\r
+ <Command>\r
+ </Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <Link>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ <PreBuildEvent>\r
+ <Command>\r
+ </Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <ImportGroup Label="ExtensionTargets">\r
+ </ImportGroup>\r
+</Project>
\ No newline at end of file
<MONO_PATH_ENV>MONO_PATH=$(MONO_PATH)</MONO_PATH_ENV>
<MONO_CFG_DIR_ENV>MONO_CFG_DIR=$(MONO_CFG_DIR)</MONO_CFG_DIR_ENV>
<MONO_TOOLCHAIN_PATH_ENV>PATH=$(MONO_TOOLCHAIN_PATH)</MONO_TOOLCHAIN_PATH_ENV>
- <MONO_LOG_LEVEL_ENV>MONO_LOG_LEVEL=debug</MONO_LOG_LEVEL_ENV>
- <MONO_LOG_MASK_ENV>MONO_LOG_MASK=all</MONO_LOG_MASK_ENV>
+ <MONO_LOG_LEVEL_ENV>MONO_LOG_LEVEL=</MONO_LOG_LEVEL_ENV>
+ <MONO_LOG_MASK_ENV>MONO_LOG_MASK=</MONO_LOG_MASK_ENV>
</PropertyGroup>
<ItemGroup>
<BuildMacro Include="MONO_PATH_ENV">
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="UserMacros">
+ <MONO_TESTDRIVER_TEST_DIR>$(MONO_DIR)/mono/tests</MONO_TESTDRIVER_TEST_DIR>
+ <MONO_PATH>$(MONO_PATH);$(MONO_TESTDRIVER_TEST_DIR)</MONO_PATH>
+ <MONO_CONFIG_PATH>$(MONO_EXECUTABLE_DIR)\tests-config.xml</MONO_CONFIG_PATH>
+ <MONO_CONFIG_ARG>--config "$(MONO_CONFIG_PATH)"</MONO_CONFIG_ARG>
+ <MONO_TESTDRIVER_RUN_TARGET>winx64structs.exe</MONO_TESTDRIVER_RUN_TARGET>
+ <MONO_TESTDRIVER_RUN_ADDITIONAL_ARGS>
+ </MONO_TESTDRIVER_RUN_ADDITIONAL_ARGS>
+ <MONO_TESTDRIVER_RUN_ARGS>$(MONO_CONFIG_ARG) "$(MONO_TESTDRIVER_RUN_TARGET)" $(MONO_TESTDRIVER_RUN_ADDITIONAL_ARGS)</MONO_TESTDRIVER_RUN_ARGS>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="MONO_TESTDRIVER_TEST_DIR">
+ <Value>$(MONO_TESTDRIVER_TEST_DIR)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_PATH">
+ <Value>$(MONO_PATH)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_CONFIG_PATH">
+ <Value>$(MONO_CONFIG_PATH)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_CONFIG_ARG">
+ <Value>$(MONO_CONFIG_ARG)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_TESTDRIVER_RUN_TARGET">
+ <Value>$(MONO_TESTDRIVER_RUN_TARGET)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_TESTDRIVER_RUN_ADDITIONAL_ARGS">
+ <Value>$(MONO_TESTDRIVER_RUN_ADDITIONAL_ARGS)</Value>
+ </BuildMacro>
+ <BuildMacro Include="MONO_TESTDRIVER_RUN_ARGS">
+ <Value>$(MONO_TESTDRIVER_RUN_ARGS)</Value>
+ </BuildMacro>
+ </ItemGroup>
+ <ItemDefinitionGroup />
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup Label="ProjectConfigurations">\r
+ <ProjectConfiguration Include="Debug|Win32">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|Win32">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|x64">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|x64">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ProjectReference Include="mono.vcxproj">\r
+ <Project>{a0eddcd9-940f-432c-a28f-7ef322437d79}</Project>\r
+ </ProjectReference>\r
+ </ItemGroup>\r
+ <PropertyGroup Label="Globals">\r
+ <ProjectGuid>{7BECCFA0-28A0-4995-9856-558560F720E6}</ProjectGuid>\r
+ <Keyword>Win32Proj</Keyword>\r
+ <RootNamespace>monotestdrivertest</RootNamespace>\r
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+ <ConfigurationType>Utility</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+ <ImportGroup Label="ExtensionSettings">\r
+ </ImportGroup>\r
+ <ImportGroup Label="Shared">\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-Win32.props" />\r
+ <Import Project="mono-testdriver-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-Win32.props" />\r
+ <Import Project="mono-testdriver-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-x64.props" />\r
+ <Import Project="mono-testdriver-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ <Import Project="mono.props" />\r
+ <Import Project="mono-test.props" />\r
+ <Import Project="mono-test-x64.props" />\r
+ <Import Project="mono-testdriver-test.props" />\r
+ <Import Project="mono-test-env.props" />\r
+ </ImportGroup>\r
+ <PropertyGroup Label="UserMacros" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ <OutDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\</OutDir>\r
+ <IntDir>$(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <LocalDebuggerCommandArguments>$(MONO_TESTDRIVER_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_TESTDRIVER_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_TESTDRIVER_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_TESTDRIVER_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_TESTDRIVER_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_TESTDRIVER_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LocalDebuggerCommand>$(MONO_EXECUTABLE)</LocalDebuggerCommand>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ <LocalDebuggerCommandArguments>$(MONO_TESTDRIVER_RUN_ARGS)</LocalDebuggerCommandArguments>\r
+ <LocalDebuggerWorkingDirectory>$(MONO_TESTDRIVER_TEST_DIR)</LocalDebuggerWorkingDirectory>\r
+ <LocalDebuggerEnvironment>$(MONO_PATH_ENV)\r
+$(MONO_CFG_DIR_ENV)\r
+$(MONO_TOOLCHAIN_PATH_ENV)\r
+$(MONO_LOG_LEVEL_ENV)\r
+$(MONO_LOG_MASK_ENV)\r
+$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\r
+ </PropertyGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <PreBuildEvent>\r
+ <Command>test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86</Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <PreBuildEvent>\r
+ <Command>test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86-64</Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <Link>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ <PreBuildEvent>\r
+ <Command>test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86</Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <SDLCheck>true</SDLCheck>\r
+ </ClCompile>\r
+ <Link>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ <PreBuildEvent>\r
+ <Command>test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86-64</Command>\r
+ </PreBuildEvent>\r
+ </ItemDefinitionGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <ImportGroup Label="ExtensionTargets">\r
+ </ImportGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file
<MONO_USE_SEPARATE_BUILD_DIR>true</MONO_USE_SEPARATE_BUILD_DIR>
<!-- When true, all binaries and libraries will link using static c-runtime. When false, all binaries and libraries will link using dynamic c-runtime. -->
<MONO_USE_STATIC_C_RUNTIME>false</MONO_USE_STATIC_C_RUNTIME>
+ <!-- When true, mono binaries will link using static libmono. When false, mono binaries will link using dynamic libmono. -->
+ <MONO_USE_STATIC_LIBMONO>false</MONO_USE_STATIC_LIBMONO>
</PropertyGroup>
<PropertyGroup Label="MonoDirectories">
<top_srcdir>$(MSBuildProjectDirectory)/..</top_srcdir>
<MONO_TARGET_SUFFIX Condition="'$(MONO_USE_TARGET_SUFFIX)'=='true'">-boehm</MONO_TARGET_SUFFIX>
<MONO_BUILD_DIR_PREFIX Condition="'$(MONO_USE_SEPARATE_BUILD_DIR)'=='true'">$(MONO_BUILD_DIR_PREFIX)boehm/</MONO_BUILD_DIR_PREFIX>
</PropertyGroup>
+ <PropertyGroup Label="Static-Mono-Libraries">
+ <MONO_RUNTIME_LIBS>libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;$(GC_LIB)</MONO_RUNTIME_LIBS>
+ <MONO_STATIC_LIBMONO_LIB>libmono-static$(MONO_TARGET_SUFFIX).lib;$(MONO_RUNTIME_LIBS)</MONO_STATIC_LIBMONO_LIB>
+ <MONO_DYNAMIC_LIBMONO_LIB>mono-2.0$(MONO_TARGET_SUFFIX).lib</MONO_DYNAMIC_LIBMONO_LIB>
+ </PropertyGroup>
+ <PropertyGroup Label="Static-libmono-Library" Condition="$(MONO_USE_STATIC_LIBMONO)=='true'">
+ <MONO_LIBMONO_LIB>$(MONO_STATIC_LIBMONO_LIB)</MONO_LIBMONO_LIB>
+ </PropertyGroup>
+ <PropertyGroup Label="Dynamic-libmono-Library" Condition="$(MONO_USE_STATIC_LIBMONO)!='true'">
+ <MONO_LIBMONO_LIB>$(MONO_DYNAMIC_LIBMONO_LIB)</MONO_LIBMONO_LIB>
+ </PropertyGroup>
<PropertyGroup Label="MonoProfiler">
<VTUNE_INCLUDE_DIR>$(ProgramFiles)/Intel/VTune Amplifier XE 2013/include</VTUNE_INCLUDE_DIR>
</PropertyGroup>
<BuildMacro Include="MONO_USE_STATIC_C_RUNTIME">
<Value>$(MONO_USE_STATIC_C_RUNTIME)</Value>
</BuildMacro>
+ <BuildMacro Include="MONO_USE_STATIC_LIBMONO">
+ <Value>$(MONO_USE_STATIC_LIBMONO)</Value>
+ </BuildMacro>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-mini-regression-test", "mono-mini-regression-test.vcxproj", "{3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}"\r
EndProject\r
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "regression", "regression", "{A0068765-334B-414C-8E21-8376CD2EC9F6}"\r
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "jit", "jit", "{A0068765-334B-414C-8E21-8376CD2EC9F6}"\r
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmono-static", "libmono-static.vcxproj", "{CB0D9E92-293C-439C-9AC7-C5F59B6E0772}"\r
EndProject\r
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-full-aot-run-test", "mono-full-aot-run-test.vcxproj", "{6C64262B-077B-4E12-AF91-9409ECCB75F6}"\r
EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-testdriver-test", "mono-testdriver-test.vcxproj", "{7BECCFA0-28A0-4995-9856-558560F720E6}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-nunit-test", "mono-nunit-test.vcxproj", "{0046B994-40A8-4C64-AC9D-429DC9177B54}"\r
+EndProject\r
Global\r
GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
Debug|Win32 = Debug|Win32\r
{6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|Win32.Build.0 = Release|Win32\r
{6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|x64.ActiveCfg = Release|x64\r
{6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|x64.Build.0 = Release|x64\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|Win32.Build.0 = Debug|Win32\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|x64.ActiveCfg = Debug|x64\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|x64.Build.0 = Debug|x64\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|Win32.ActiveCfg = Release|Win32\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|Win32.Build.0 = Release|Win32\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|x64.ActiveCfg = Release|x64\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|x64.Build.0 = Release|x64\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|Win32.Build.0 = Debug|Win32\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|x64.ActiveCfg = Debug|x64\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|x64.Build.0 = Debug|x64\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|Win32.ActiveCfg = Release|Win32\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|Win32.Build.0 = Release|Win32\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|x64.ActiveCfg = Release|x64\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|x64.Build.0 = Release|x64\r
EndGlobalSection\r
GlobalSection(SolutionProperties) = preSolution\r
HideSolutionNode = FALSE\r
{BACF489E-EAEB-42BF-9E0A-C54D7CF455B4} = {ECA11C76-E192-4F67-A8FA-28B637D9716F}\r
{C7D83158-4EB6-4409-8730-612AD45FAF6A} = {BACF489E-EAEB-42BF-9E0A-C54D7CF455B4}\r
{6C64262B-077B-4E12-AF91-9409ECCB75F6} = {BACF489E-EAEB-42BF-9E0A-C54D7CF455B4}\r
+ {7BECCFA0-28A0-4995-9856-558560F720E6} = {A0068765-334B-414C-8E21-8376CD2EC9F6}\r
+ {0046B994-40A8-4C64-AC9D-429DC9177B54} = {A0068765-334B-414C-8E21-8376CD2EC9F6}\r
EndGlobalSection\r
GlobalSection(ExtensibilityGlobals) = postSolution\r
AMDCaProjectFile = C:\Users\Owner\Development\monogit\mono\msvc\CodeAnalyst\mono.caw\r
</ClCompile>\r
<ProjectReference />\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
- <AdditionalDependencies>eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX64</TargetMachine>\r
- <AdditionalDependencies>eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX64</TargetMachine>\r
- <AdditionalDependencies>eglib.lib;mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX86</TargetMachine>\r
<ModuleDefinitionFile>mono-profiler-vtune.def</ModuleDefinitionFile>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
</Link>\r
<ProjectReference>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<ModuleDefinitionFile>mono-profiler-vtune.def</ModuleDefinitionFile>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
</Link>\r
<ProjectReference>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
</ClCompile>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Windows</SubSystem>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
</ClCompile>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Windows</SubSystem>\r
--- /dev/null
+@ECHO off
+
+SET MONO_RESULT=1
+SET CONFIG_PATH=%1
+SET MONO_MODULE_PATH=%2
+SET CPU_ARCH=%3
+
+IF "" == "%CONFIG_PATH%" (
+ ECHO Error: No configuration path set.
+ GOTO ON_ERROR
+)
+
+IF "" == "%MONO_MODULE_PATH%" (
+ ECHO Error: No mono module path set.
+ GOTO ON_ERROR
+)
+
+IF "" == "%CPU_ARCH%" (
+ ECHO Error: No cpu architecture set.
+ GOTO ON_ERROR
+)
+
+IF NOT "x86" == "%CPU_ARCH%" (
+
+ IF NOT "x86-64" == "%CPU_ARCH%" (
+ ECHO Error: Unknown cpu architecture, %CPU_ARCH%.
+ GOTO ON_ERROR
+ )
+)
+
+SET CONFIG_PATH=%CONFIG_PATH:"=%
+SET CONFIG_PATH=%CONFIG_PATH:/=\%
+
+SET MONO_MODULE_PATH=%MONO_MODULE_PATH:"=%
+SET MONO_MODULE_PATH=%MONO_MODULE_PATH:/=\%
+
+REM Setup test configuration file.
+>%CONFIG_PATH% ECHO ^<configuration^>
+>>%CONFIG_PATH% ECHO ^<dllmap os="windows" cpu="%CPU_ARCH%" dll="libtest" target="%MONO_MODULE_PATH%\libtest.dll" /^>
+>>%CONFIG_PATH% ECHO ^</configuration^>
+
+SET MONO_RESULT=0
+ECHO Successfully setup test configuration file, %CONFIG_PATH%.
+
+GOTO ON_EXIT
+
+:ON_ERROR
+ ECHO Failed to setup test configuration file.
+ ECHO test-config-setup.bat [CONFIG_FILE_PATH] [MONO_MODULE_PATH] [x86|x86-64]
+ SET MONO_RESULT=1
+ GOTO ON_EXIT
+
+:ON_EXIT
+ EXIT /b %MONO_RESULT%
+
+@ECHO on
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX64</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX64</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
<LinkLibraryDependencies>false</LinkLibraryDependencies>\r
</ProjectReference>\r
<Link>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>true</OptimizeReferences>\r
<EnableCOMDATFolding>true</EnableCOMDATFolding>\r
<TargetMachine>MachineX64</TargetMachine>\r
- <AdditionalDependencies>mono-2.0$(MONO_TARGET_SUFFIX).lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalDependencies>$(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies)</AdditionalDependencies>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
)
)
-%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %WIN_CONFIG_H% %CONFIG_H% %CONFIGURE_AC% >$null 2>&1
+%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %WIN_CONFIG_H% %CONFIG_H% %CONFIGURE_AC% 2>&1
IF NOT %ERRORLEVEL% == 0 (
ECHO copy %WIN_CONFIG_H% %CONFIG_H%
copy %WIN_CONFIG_H% %CONFIG_H%
- %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -Command "(Get-Content %CONFIG_H%) -replace '#MONO_VERSION#', (Select-String -path %CONFIGURE_AC% -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content %CONFIG_H%" >$null 2>&1
+ %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -Command "(Get-Content %CONFIG_H%) -replace '#MONO_VERSION#', (Select-String -path %CONFIGURE_AC% -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content %CONFIG_H%" 2>&1
)
-%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H% >$null 2>&1
+%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H% 2>&1
IF NOT %ERRORLEVEL% == 0 (
ECHO copy %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H%
)
SET VERSION_CONTENT="#define FULL_VERSION \"Visual Studio built mono\""
-%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-content.ps1 %VERSION_CONTENT% %VERSION_H%
+%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-content.ps1 %VERSION_CONTENT% %VERSION_H% 2>&1
IF NOT %ERRORLEVEL% == 0 (
fi
if [[ ${CI_TAGS} == *'acceptance-tests'* ]];
-then $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh
-else make check-ci
-fi
\ No newline at end of file
+ then
+ $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh
+elif [[ ${CI_TAGS} == *'profiler-stress-tests'* ]];
+ then
+ $(dirname "${BASH_SOURCE[0]}")/run-test-profiler-stress-tests.sh
+else
+ make check-ci
+fi
--- /dev/null
+#!/bin/bash -e
+
+export TESTCMD=`dirname "${BASH_SOURCE[0]}"`/run-step.sh
+
+${TESTCMD} --label=check-profiler-stress --timeout=20h make -C acceptance-tests check-profiler-stress