From 7e4f7fef91b8a8cb39db821fb18c56b0cbfffcc8 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 25 Sep 2024 21:06:11 +0200 Subject: [PATCH 1/4] [builds] Legacy Xamarin cleanup. --- Make.config | 17 +--- builds/.gitignore | 28 ------ builds/Makefile | 85 +++---------------- builds/Mono.framework-Info.plist | 58 ------------- builds/Mono.framework-tvos.Info.plist | 56 ------------ builds/Mono.framework-watchos.Info.plist | 56 ------------ builds/mac-System.config | 3 - builds/mono-wrapper.in | 7 -- tests/Makefile | 4 +- tests/xharness/Harness.cs | 2 - tests/xharness/IHarness.cs | 1 - .../scripts/bash/export-mono-filenames.sh | 27 ------ .../automation/templates/build/build.yml | 14 --- .../automation/templates/tests/run-tests.yml | 1 - 14 files changed, 14 insertions(+), 345 deletions(-) delete mode 100644 builds/Mono.framework-Info.plist delete mode 100644 builds/Mono.framework-tvos.Info.plist delete mode 100644 builds/Mono.framework-watchos.Info.plist delete mode 100644 builds/mac-System.config delete mode 100644 builds/mono-wrapper.in delete mode 100755 tools/devops/automation/scripts/bash/export-mono-filenames.sh diff --git a/Make.config b/Make.config index fb8642a8b92c..fd3e1280186e 100644 --- a/Make.config +++ b/Make.config @@ -643,22 +643,7 @@ JENKINS_RESULTS_DIRECTORY ?= $(abspath $(TOP)/jenkins-results) # Clone files instead of copying them on APFS file systems. Much faster. CP:=$(shell df -t apfs / >/dev/null 2>&1 && echo "cp -c" || echo "cp") -# WORKAROUND, Ideally it should be xcode-$(XCODE_PRODUCT_BUILD_VERSION) but mono does not build binaries for each xcode release -# Xcode 12.4 Build 12D4e -XCODE_IOS_ARCHIVE_VERSION=xcode-12D4e -# Xcode 12.4 Build 12D4e -XCODE_MACOS_ARCHIVE_VERSION=xcode-12D4e -MONO_IOS_FILENAME:=ios-release-Darwin-$(MONO_HASH).7z -MONO_IOS_URL:=https://download.mono-project.com/mono-sdks/$(XCODE_IOS_ARCHIVE_VERSION)/$(MONO_IOS_FILENAME) - -# Setup various variables depending on whether mono is downloaded or built from source -ifeq ($(MONO_BUILD_FROM_SOURCE),) -MONO_IOS_SDK_DESTDIR:=$(abspath $(TOP)/builds/downloads/$(basename $(MONO_IOS_FILENAME))) -MONO_BUILD_MODE=download-mono -else -MONO_IOS_SDK_DESTDIR:=$(abspath $(MONO_PATH)/sdks/out) -MONO_BUILD_MODE=compile-mono -endif +MONO_IOS_SDK_DESTDIR:=$(abspath $(TOP)/builds/downloads/mono-ios-sdk-destdir) # This variable includes all the platforms we support, even those that might be disabled in this build. ALL_PLATFORMS=iOS tvOS watchOS macOS diff --git a/builds/.gitignore b/builds/.gitignore index dad605eee05e..e258969d6dcd 100644 --- a/builds/.gitignore +++ b/builds/.gitignore @@ -3,31 +3,3 @@ dotnet-install.sh BundledNETCorePlatformsPackageVersion.txt downloads .stamp* -.deps.*.mk -*.config.cache -install -mac32 -mac64 -llvm -llvm64 -simulator86 -simulator64 -watchsimulator -tvsimulator -tools64 -cross -cross64 -crosstv -cross-watch -target7 -target7s -target64 -targettv -targetwatch -watchbcl -mono-ios-sdk-destdir -*.dylib -*.o -x86-64-slice* -*.pkg - diff --git a/builds/Makefile b/builds/Makefile index 3a33d9754283..4847fb7d9b4e 100644 --- a/builds/Makefile +++ b/builds/Makefile @@ -10,68 +10,22 @@ else DOTNET_ARCH=x64 endif -## -## Mono download vs. build -## - -download: download-mono -download-mono: \ - downloads/$(basename $(MONO_IOS_FILENAME)) \ - -downloads/$(basename $(MONO_IOS_FILENAME)): MONO_URL=$(MONO_IOS_URL) - include $(TOP)/mk/colors.mk -DOWNLOADS = \ - downloads/$(MONO_IOS_FILENAME) \ - -# This target downloads the mono archives, there's one for Xamarin.iOS and one for Xamarin.Mac. -# If doing many clean builds, it's possible to copy the downloaded zip file to ~/Library/Caches/xamarin-macios -# to avoid having to download it every time. The zip files have to be copied manually, otherwise -# we'd end up filling up a lot of hard drives around the world. -$(DOWNLOADS): - $(Q) mkdir -p downloads - $(Q) echo "Downloading $(MONO_URL)..." - $(Q) if test -f ~/Library/Caches/xamarin-macios/$(notdir $@); then \ - echo "Found a cached version of $(MONO_URL) in ~/Library/Caches/xamarin-macios/$(notdir $@)."; \ - $(CP) ~/Library/Caches/xamarin-macios/$(notdir $@) $@.tmp; \ - else \ - EC=0; \ - $(CURL_RETRY) $(MONO_URL) --output $@.tmp || EC=$$?; \ - if [[ x$$EC == x22 ]]; then \ - MSG="Could not download the archive %s because the URL doesn't exist. This can happen if bumping mono very soon after the corresponding commit was pushed to mono (i.e. the archive hasn't been built yet). If so, please wait a bit and try again."; \ - printf "$(COLOR_RED)*** $$MSG$(COLOR_CLEAR)\n" "$(notdir $@)"; \ - if test -n "$$FAILURE_REASON_PATH"; then printf "$$MSG\n" "[$(notdir $@)]($(MONO_URL))" >> "$$FAILURE_REASON_PATH"; fi; \ - fi; \ - if [[ x$$EC != x0 ]]; then exit $$EC; fi; \ - if [[ "x$$MACIOS_CACHE_DOWNLOADS" != "x" ]]; then \ - mkdir -p ~/Library/Caches/xamarin-macios/; \ - $(CP) $@.tmp ~/Library/Caches/xamarin-macios/"$(notdir $@)"; \ - echo "Cached the download of $(notdir $@) in ~/Library/Caches/xamarin-macios"; \ - fi; \ - fi - $(Q) mv $@.tmp $@ - $(Q) echo "Downloaded $(MONO_URL)" - -downloads/%: downloads/%.7z - $(Q) echo "Unzipping $*..." - $(Q) rm -Rf $@.tmp - $(Q) 7z x $< -o$@.tmp - $(Q) find $@.tmp -exec touch {} + - $(Q) mv $@.tmp $@ - $(Q) echo "Unzipped $*." - -downloads/%: downloads/%.nupkg - $(Q) echo "Unzipping $*..." - $(Q) rm -Rf $@.tmp - $(Q) unzip -d $@.tmp $< - $(Q) find $@.tmp -exec touch {} + - $(Q) mv $@.tmp $@ - $(Q) echo "Unzipped $*." +DOTNET_FILENAME=$(DOTNET_VERSION).tar.gz +DOTNET_CACHE_FILENAME=$(HOME)/Library/Caches/xamarin-macios/$(DOTNET_FILENAME) downloads/$(DOTNET_INSTALL_NAME): dotnet-install.sh $(Q) echo "Downloading and installing .NET $(DOTNET_VERSION) into $@..." - $(Q) ./dotnet-install.sh --install-dir "$@.tmp" --version "$(DOTNET_VERSION)" --architecture $(DOTNET_ARCH) --no-path $$DOTNET_INSTALL_EXTRA_ARGS + $(Q) if test -f $(DOTNET_CACHE_FILENAME); then \ + echo "Found a cached version of .NET $(DOTNET_VERSION) in $(DOTNET_CACHE_FILENAME)."; \ + mkdir -p "$@.tmp"; \ + tar -xzf $(DOTNET_CACHE_FILENAME) -C "$@.tmp"; \ + else \ + ./dotnet-install.sh --install-dir "$@.tmp" --version "$(DOTNET_VERSION)" --architecture $(DOTNET_ARCH) --no-path --keep-zip --zip-path "downloads/$(DOTNET_FILENAME)" $$DOTNET_INSTALL_EXTRA_ARGS; \ + cp -c downloads/$(DOTNET_FILENAME) $(DOTNET_CACHE_FILENAME); \ + echo "Cached the download of $(DOTNET_FILENAME) in ~/Library/Caches/xamarin-macios"; \ + fi $(Q) rm -Rf "$@" $(Q) mv "$@.tmp" "$@" $(Q) echo "Downloaded and installed .NET $(DOTNET_VERSION) into $@." @@ -106,10 +60,6 @@ dotnet-install.sh: Makefile $(Q) chmod +x $@.tmp $(Q) mv $@.tmp $@ -.stamp-download-mono: $(TOP)/Make.config $(TOP)/mk/mono.mk - $(MAKE) download-mono - $(Q) touch $@ - ifdef CUSTOM_DOTNET DOWNLOAD_DOTNET_VERSION=$(CUSTOM_DOTNET_VERSION) else @@ -168,17 +118,7 @@ dotnet:: $(DOTNET_DOWNLOADS) all-local:: $(DOTNET_DOWNLOADS) clean-local:: - $(Q) rm -Rf downloads .stamp-download-mono - -all-local:: .stamp-mono-ios-sdk-destdir - -.stamp-mono-ios-sdk-destdir: .stamp-$(MONO_BUILD_MODE) - ln -sf $(MONO_IOS_SDK_DESTDIR) mono-ios-sdk-destdir - $(Q) touch $@ - -# -# .NET -# + $(Q) rm -Rf downloads DOTNET_COMMON_DIRECTORIES += \ $(foreach platform,$(DOTNET_PLATFORMS_UPPERCASE),$(DOTNET_DESTDIR)/$($(platform)_NUGET_SDK_NAME)) \ @@ -212,4 +152,3 @@ $(DOTNET_COMMON_DIRECTORIES): install-dotnet: $(DOTNET_COMMON_TARGETS) install-local:: install-dotnet all-local:: install-dotnet - diff --git a/builds/Mono.framework-Info.plist b/builds/Mono.framework-Info.plist deleted file mode 100644 index 01fc5bc84ef9..000000000000 --- a/builds/Mono.framework-Info.plist +++ /dev/null @@ -1,58 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleIdentifier - xamarin.ios.mono-framework - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Mono - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 3.12 - NSPrincipalClass - - CFBundleExecutable - Mono - - BuildMachineOSBuild - 13F34 - CFBundleDevelopmentRegion - en - CFBundleSupportedPlatforms - - iPhoneOS - - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 12D508 - DTPlatformName - iphoneos - DTPlatformVersion - 8.2 - DTSDKBuild - 12D508 - DTSDKName - iphoneos8.2 - DTXcode - 0620 - DTXcodeBuild - 6C131e - MinimumOSVersion - 11.0 - UIDeviceFamily - - 1 - 2 - - - diff --git a/builds/Mono.framework-tvos.Info.plist b/builds/Mono.framework-tvos.Info.plist deleted file mode 100644 index 33e53dcd77f7..000000000000 --- a/builds/Mono.framework-tvos.Info.plist +++ /dev/null @@ -1,56 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleIdentifier - xamarin.tvos.mono-framework - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Mono - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 3.12 - NSPrincipalClass - - CFBundleExecutable - Mono - BuildMachineOSBuild - 13F34 - CFBundleDevelopmentRegion - en - CFBundleSupportedPlatforms - - AppleTVOS - - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 12D508 - DTPlatformName - appletvos - DTPlatformVersion - 9.0 - DTSDKBuild - 12D508 - DTSDKName - appletvos9.0 - DTXcode - 0620 - DTXcodeBuild - 6C131e - MinimumOSVersion - 11.0 - UIDeviceFamily - - 3 - - - diff --git a/builds/Mono.framework-watchos.Info.plist b/builds/Mono.framework-watchos.Info.plist deleted file mode 100644 index d49a2c154e7f..000000000000 --- a/builds/Mono.framework-watchos.Info.plist +++ /dev/null @@ -1,56 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleIdentifier - xamarin.watchos.mono-framework - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Mono - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 3.12 - NSPrincipalClass - - CFBundleExecutable - Mono - BuildMachineOSBuild - 13F34 - CFBundleDevelopmentRegion - en - CFBundleSupportedPlatforms - - WatchOS - - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 12D508 - DTPlatformName - watchos - DTPlatformVersion - 2.0 - DTSDKBuild - 12D508 - DTSDKName - watchos2.2 - DTXcode - 0620 - DTXcodeBuild - 6C131e - MinimumOSVersion - 4.0 - UIDeviceFamily - - 4 - - - diff --git a/builds/mac-System.config b/builds/mac-System.config deleted file mode 100644 index ebb9b2987fd1..000000000000 --- a/builds/mac-System.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/builds/mono-wrapper.in b/builds/mono-wrapper.in deleted file mode 100644 index d57106b82ccf..000000000000 --- a/builds/mono-wrapper.in +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -export PATH="@FRAMEWORK_ROOT@/bin:$PATH" -export MONO_CFG_DIR="@FRAMEWORK_ROOT@/etc" -export MONO_PATH="@FRAMEWORK_ROOT@/lib/@ARCH@:@FRAMEWORK_ROOT@/lib/mono/Xamarin.Mac" - -"@MONO@" "$@" diff --git a/tests/Makefile b/tests/Makefile index b242791bc3ff..847e1807f83c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -62,7 +62,6 @@ test.config: Makefile $(TOP)/Make.config $(TOP)/mk/mono.mk $(TOP)/eng/Version.De @echo "JENKINS_RESULTS_DIRECTORY=$(abspath $(JENKINS_RESULTS_DIRECTORY))" >> $@ @echo "INCLUDE_DEVICE=$(INCLUDE_DEVICE)" >> $@ @echo "XCODE_DEVELOPER_ROOT=$(XCODE_DEVELOPER_ROOT)" >> $@ - @echo "MONO_IOS_SDK_DESTDIR=$(MONO_IOS_SDK_DESTDIR)" >> $@ @echo "DOTNET=$(DOTNET)" >> $@ @echo "IOS_SDK_VERSION=$(IOS_SDK_VERSION)" >> $@ @echo "TVOS_SDK_VERSION=$(TVOS_SDK_VERSION)" >> $@ @@ -96,7 +95,6 @@ test-system.config: Makefile $(TOP)/Make.config $(TOP)/mk/mono.mk $(TOP)/eng/Ver @echo "MAC_DESTDIR=/" >> $@ @echo "JENKINS_RESULTS_DIRECTORY=$(abspath $(JENKINS_RESULTS_DIRECTORY))" >> $@ @echo "INCLUDE_DEVICE=$(INCLUDE_DEVICE)" >> $@ - @echo "MONO_IOS_SDK_DESTDIR=$(MONO_IOS_SDK_DESTDIR)" >> $@ @echo "DOTNET=$(DOTNET)" >> $@ @echo "IOS_SDK_VERSION=$(IOS_SDK_VERSION)" >> $@ @echo "TVOS_SDK_VERSION=$(TVOS_SDK_VERSION)" >> $@ @@ -339,7 +337,7 @@ runner: $(XHARNESS_EXECUTABLE) # This makefile target will run the device tests using the Xamarin.iOS version # installed on the system. vsts-device-tests: $(XHARNESS_EXECUTABLE) - $(MAKE) -C $(TOP)/builds .stamp-mono-ios-sdk-destdir download -j + $(MAKE) -C $(TOP)/builds download -j $(Q) ulimit -n 4096 && $(DOTNET) $< $(XHARNESS_VERBOSITY) --jenkins --autoconf --rootdir $(CURDIR) --sdkroot $(XCODE_DEVELOPER_ROOT) --use-system:true --label=skip-all-tests,run-device-tests --markdown-summary=$(CURDIR)/TestSummary.md $(TESTS_EXTRA_ARGUMENTS) $(TESTS_PERIODIC_COMMAND) verify-system-vsmac-xcode-match: diff --git a/tests/xharness/Harness.cs b/tests/xharness/Harness.cs index 2d6f5b1bc2d0..f3fd496b986b 100644 --- a/tests/xharness/Harness.cs +++ b/tests/xharness/Harness.cs @@ -229,7 +229,6 @@ string GetVariable (string variable, string @default = null) public string JENKINS_RESULTS_DIRECTORY { get; } // Use same name as in Makefiles, so that a grep finds it. public string MAC_DESTDIR { get; } public string IOS_DESTDIR { get; } - public string MONO_IOS_SDK_DESTDIR { get; } public bool ENABLE_DOTNET { get; } public bool INCLUDE_XAMARIN_LEGACY { get; } public string SYSTEM_MONO { get; set; } @@ -305,7 +304,6 @@ public Harness (IResultParser resultParser, HarnessAction action, HarnessConfigu INCLUDE_MACCATALYST = IsVariableSet (nameof (INCLUDE_MACCATALYST)); MAC_DESTDIR = GetVariable (nameof (MAC_DESTDIR)); IOS_DESTDIR = GetVariable (nameof (IOS_DESTDIR)); - MONO_IOS_SDK_DESTDIR = GetVariable (nameof (MONO_IOS_SDK_DESTDIR)); ENABLE_DOTNET = IsVariableSet (nameof (ENABLE_DOTNET)); SYSTEM_MONO = GetVariable (nameof (SYSTEM_MONO)); DOTNET_DIR = GetVariable (nameof (DOTNET_DIR)); diff --git a/tests/xharness/IHarness.cs b/tests/xharness/IHarness.cs index 4c2ba87a8faf..b20f6a2f006e 100644 --- a/tests/xharness/IHarness.cs +++ b/tests/xharness/IHarness.cs @@ -40,7 +40,6 @@ public interface IHarness { string JENKINS_RESULTS_DIRECTORY { get; } string MAC_DESTDIR { get; } string IOS_DESTDIR { get; } - string MONO_IOS_SDK_DESTDIR { get; } bool ENABLE_DOTNET { get; } bool INCLUDE_XAMARIN_LEGACY { get; } string SYSTEM_MONO { get; set; } diff --git a/tools/devops/automation/scripts/bash/export-mono-filenames.sh b/tools/devops/automation/scripts/bash/export-mono-filenames.sh deleted file mode 100755 index ac0fe56c31f1..000000000000 --- a/tools/devops/automation/scripts/bash/export-mono-filenames.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -eu - -env | sort - -set -o pipefail -IFS=$'\n\t ' - -FILE=$(pwd)/tmp.txt - -make -C "$BUILD_SOURCESDIRECTORY/xamarin-macios/tools/devops" print-variable-value-to-file FILE="$FILE" VARIABLE=MONO_IOS_FILENAME -MONO_IOS_FILENAME=$(cat "$FILE") -MONO_IOS_FILENAME=$(basename "$MONO_IOS_FILENAME" ".7z") - -make -C "$BUILD_SOURCESDIRECTORY/xamarin-macios/tools/devops" print-variable-value-to-file FILE="$FILE" VARIABLE=MONO_MAC_FILENAME -MONO_MAC_FILENAME=$(cat "$FILE") -MONO_MAC_FILENAME=$(basename "$MONO_MAC_FILENAME" ".7z") - -make -C "$BUILD_SOURCESDIRECTORY/xamarin-macios/tools/devops" print-variable-value-to-file FILE="$FILE" VARIABLE=MONO_MACCATALYST_FILENAME -MONO_MACCATALYST_FILENAME=$(cat "$FILE") -MONO_MACCATALYST_FILENAME=$(basename "$MONO_MACCATALYST_FILENAME" ".7z") - -# allow the rest of the build use the values -echo "##vso[task.setvariable variable=MONO_IOS_FILENAME;]$MONO_IOS_FILENAME" -echo "##vso[task.setvariable variable=MONO_MAC_FILENAME;]$MONO_MAC_FILENAME" -echo "##vso[task.setvariable variable=MONO_MACCATALYST_FILENAME;]$MONO_MACCATALYST_FILENAME" - -rm -f "$FILE" diff --git a/tools/devops/automation/templates/build/build.yml b/tools/devops/automation/templates/build/build.yml index 7838afd4894c..eefa0ba21c7e 100644 --- a/tools/devops/automation/templates/build/build.yml +++ b/tools/devops/automation/templates/build/build.yml @@ -167,20 +167,6 @@ steps: rm -rf ~/Library/Caches/com.apple.dt.Xcode displayName: 'Clear Xcode cache' - # downloding mono takes time and has been shown to be problematic when we have network issues. This is why we - # are using the cache. Mono does not get bump a lot of times if any (after dotnet) - - - bash: $(System.DefaultWorkingDirectory)/xamarin-macios/tools/devops/automation/scripts/bash/export-mono-filenames.sh - displayName: "Export mono download filenames" - workingDirectory: "$(Build.SourcesDirectory)/xamarin-macios" - timeoutInMinutes: 5 - - - task: Cache@2 - displayName: 'Cache iOS Mono download' - inputs: - key: "$(MONO_IOS_FILENAME)" - path: "$(Build.SourcesDirectory)/xamarin-macios/builds/downloads/$(MONO_IOS_FILENAME)" - # Actual build of the project - bash: $(System.DefaultWorkingDirectory)/xamarin-macios/tools/devops/automation/scripts/bash/build-macios.sh name: build diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml index f625ab48d289..ada31af1f8b1 100644 --- a/tools/devops/automation/templates/tests/run-tests.yml +++ b/tools/devops/automation/templates/tests/run-tests.yml @@ -148,7 +148,6 @@ steps: env -0 | sort -z | tr '\0' '\n' || true make -C builds download -j - make -C builds .stamp-mono-ios-sdk-destdir -j make -C tests ${{ parameters.makeTarget }} # We reached the end! This means we succeeded! From e4958fd0f7363150836fa3975e65c4efcaaf8c26 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 25 Sep 2024 21:11:09 +0200 Subject: [PATCH 2/4] Add source code from the mono library. --- .../src/linker/Linker.Steps/BaseStep.cs | 83 + .../src/linker/Linker.Steps/BlacklistStep.cs | 146 + .../src/linker/Linker.Steps/CleanStep.cs | 106 + .../linker/src/linker/Linker.Steps/IStep.cs | 34 + .../linker/Linker.Steps/LoadI18nAssemblies.cs | 103 + .../linker/Linker.Steps/LoadReferencesStep.cs | 61 + .../src/linker/Linker.Steps/MarkStep.cs | 3357 +++++++++++++++++ .../src/linker/Linker.Steps/OutputStep.cs | 299 ++ .../PreserveDependencyLookupStep.cs | 99 + .../linker/Linker.Steps/RegenerateGuidStep.cs | 48 + .../Linker.Steps/ResolveFromAssemblyStep.cs | 252 ++ .../Linker.Steps/ResolveFromXApiStep.cs | 140 + .../linker/Linker.Steps/ResolveFromXmlStep.cs | 727 ++++ .../src/linker/Linker.Steps/ResolveStep.cs | 57 + .../src/linker/Linker.Steps/SweepStep.cs | 715 ++++ .../src/linker/Linker.Steps/TypeMapStep.cs | 371 ++ .../linker/src/linker/Linker/Annotations.cs | 464 +++ .../src/linker/Linker/AssemblyAction.cs | 55 + .../src/linker/Linker/AssemblyResolver.cs | 157 + .../src/linker/Linker/AssemblyUtilities.cs | 16 + .../external/linker/src/linker/Linker/BCL.cs | 87 + .../linker/src/linker/Linker/ConsoleLogger.cs | 11 + .../src/linker/Linker/I18nAssemblies.cs | 47 + .../src/linker/Linker/IDependencyRecorder.cs | 44 + .../linker/src/linker/Linker/ILogger.cs | 15 + .../Linker/IReflectionPatternRecorder.cs | 62 + .../linker/src/linker/Linker/IXApiVisitor.cs | 47 + .../linker/src/linker/Linker/Inflater.cs | 106 + .../linker/src/linker/Linker/KnownMembers.cs | 31 + .../linker/src/linker/Linker/LinkContext.cs | 467 +++ .../linker/src/linker/Linker/LoadException.cs | 17 + .../LoggingReflectionPatternRecorder.cs | 49 + .../linker/src/linker/Linker/MarkException.cs | 27 + .../src/linker/Linker/MarkingHelpers.cs | 20 + .../linker/src/linker/Linker/MethodAction.cs | 38 + .../src/linker/Linker/MethodBodyScanner.cs | 165 + .../Linker/MethodDefinitionExtensions.cs | 97 + .../Linker/MethodReferenceExtensions.cs | 28 + .../src/linker/Linker/OutputException.cs | 17 + .../src/linker/Linker/OverrideInformation.cs | 43 + .../linker/src/linker/Linker/Pipeline.cs | 152 + .../linker/src/linker/Linker/Tracer.cs | 115 + .../linker/Linker/TypeDefinitionExtensions.cs | 44 + .../src/linker/Linker/TypeNameParser.cs | 48 + .../linker/src/linker/Linker/TypePreserve.cs | 38 + .../linker/Linker/TypeReferenceExtensions.cs | 241 ++ .../linker/src/linker/Linker/XApiReader.cs | 384 ++ .../linker/Linker/XmlDependencyRecorder.cs | 215 ++ .../Mono.Tuner/ApplyPreserveAttributeBase.cs | 164 + .../linker/src/tuner/Mono.Tuner/CecilRocks.cs | 519 +++ .../src/tuner/Mono.Tuner/CustomizeActions.cs | 93 + .../linker/src/tuner/Mono.Tuner/Dispatcher.cs | 310 ++ .../linker/src/tuner/Mono.Tuner/Extensions.cs | 36 + .../src/tuner/Mono.Tuner/FixModuleFlags.cs | 20 + .../src/tuner/Mono.Tuner/PreserveCrypto.cs | 122 + .../Mono.Tuner/PreserveSoapHttpClients.cs | 90 + .../linker/src/tuner/Mono.Tuner/Profile.cs | 78 + .../tuner/Mono.Tuner/RemoveAttributesBase.cs | 103 + .../src/tuner/Mono.Tuner/RemoveResources.cs | 63 + .../src/tuner/Mono.Tuner/RemoveSecurity.cs | 50 + .../src/tuner/Mono.Tuner/TunerAnnotations.cs | 55 + 61 files changed, 11648 insertions(+) create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BaseStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/IStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/RegenerateGuidStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyAction.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyUtilities.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/I18nAssemblies.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IXApiVisitor.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodAction.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/FixModuleFlags.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveAttributesBase.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveSecurity.cs create mode 100644 builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/TunerAnnotations.cs diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BaseStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BaseStep.cs new file mode 100644 index 000000000000..39210adc9eeb --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BaseStep.cs @@ -0,0 +1,83 @@ +// +// BaseStep.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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 Mono.Cecil; + +namespace Mono.Linker.Steps { + + public abstract class BaseStep : IStep { + + private LinkContext _context; + + public LinkContext Context { + get { return _context; } + } + + public AnnotationStore Annotations { + get { return _context.Annotations; } + } + + public Tracer Tracer { + get { return _context.Tracer; } + } + + public MarkingHelpers MarkingHelpers => _context.MarkingHelpers; + + public void Process (LinkContext context) + { + _context = context; + + if (!ConditionToProcess ()) + return; + + Process (); + + foreach (AssemblyDefinition assembly in context.GetAssemblies ()) + ProcessAssembly (assembly); + + EndProcess (); + } + + protected virtual bool ConditionToProcess () + { + return true; + } + + protected virtual void Process () + { + } + + protected virtual void EndProcess () + { + } + + protected virtual void ProcessAssembly (AssemblyDefinition assembly) + { + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs new file mode 100644 index 000000000000..f0d2db16676b --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs @@ -0,0 +1,146 @@ +// +// Blacklist.cs +// +// Author: +// Jb Evain (jb@nurv.fr) +// +// (C) 2007 Novell 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.Linq; +using System.IO; +using System.Reflection; +using System.Xml; +using System.Xml.XPath; + +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class BlacklistStep : BaseStep { + + protected override void Process () + { + foreach (string name in Assembly.GetExecutingAssembly ().GetManifestResourceNames ()) { + if (!name.EndsWith (".xml", StringComparison.OrdinalIgnoreCase) || !ShouldProcessAssemblyResource (GetAssemblyName (name))) + continue; + + try { + Context.LogMessage ($"Processing resource linker descriptor: {name}"); + AddToPipeline (GetResolveStep (name)); + } catch (XmlException ex) { + /* This could happen if some broken XML file is included. */ + Context.LogMessage ($"Error processing {name}: {ex}"); + } + } + + foreach (var asm in Context.GetAssemblies ()) { + foreach (var rsc in asm.Modules + .SelectMany (mod => mod.Resources) + .Where (res => res.ResourceType == ResourceType.Embedded) + .Where (res => res.Name.EndsWith (".xml", StringComparison.OrdinalIgnoreCase)) + .Where (res => ShouldProcessAssemblyResource (GetAssemblyName (res.Name))) + .Cast ()) { + try { + Context.LogMessage ($"Processing embedded resource linker descriptor: {rsc.Name}"); + + AddToPipeline (GetExternalResolveStep (rsc, asm)); + } catch (XmlException ex) { + /* This could happen if some broken XML file is embedded. */ + Context.LogMessage ($"Error processing {rsc.Name}: {ex}"); + } + } + } + } + + static string GetAssemblyName (string descriptor) + { + int pos = descriptor.LastIndexOf ('.'); + if (pos == -1) + return descriptor; + + return descriptor.Substring (0, pos); + } + + bool ShouldProcessAssemblyResource (string name) + { + AssemblyDefinition assembly = GetAssemblyIfReferenced (name); + + if (assembly == null) + return false; + + switch (Annotations.GetAction (assembly)) { + case AssemblyAction.Link: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + case AssemblyAction.Copy: + return true; + default: + return false; + } + } + + AssemblyDefinition GetAssemblyIfReferenced (string name) + { + foreach (AssemblyDefinition assembly in Context.GetAssemblies ()) + if (assembly.Name.Name == name) + return assembly; + + return null; + } + + protected virtual void AddToPipeline (IStep resolveStep) + { + Context.Pipeline.AddStepAfter (typeof (BlacklistStep), resolveStep); + } + + protected virtual IStep GetExternalResolveStep (EmbeddedResource resource, AssemblyDefinition assembly) + { + return new ResolveFromXmlStep (GetExternalDescriptor (resource), resource.Name, assembly, "resource " + resource.Name + " in " + assembly.FullName); + } + + static ResolveFromXmlStep GetResolveStep (string descriptor) + { + return new ResolveFromXmlStep (GetDescriptor (descriptor), "descriptor " + descriptor + " from " + Assembly.GetExecutingAssembly ().FullName); + } + + protected static XPathDocument GetExternalDescriptor (EmbeddedResource resource) + { + using (var sr = new StreamReader (resource.GetResourceStream ())) { + return new XPathDocument (sr); + } + } + + static XPathDocument GetDescriptor (string descriptor) + { + using (StreamReader sr = new StreamReader (GetResource (descriptor))) { + return new XPathDocument (sr); + } + } + + static Stream GetResource (string descriptor) + { + return Assembly.GetExecutingAssembly ().GetManifestResourceStream (descriptor); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs new file mode 100644 index 000000000000..02713d874245 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs @@ -0,0 +1,106 @@ +// +// CleanStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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 Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class CleanStep : BaseStep { + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + if (Annotations.GetAction (assembly) == AssemblyAction.Link) + CleanAssembly (assembly); + } + + static void CleanAssembly (AssemblyDefinition asm) + { + foreach (TypeDefinition type in asm.MainModule.Types) + CleanType (type); + } + + static void CleanType (TypeDefinition type) + { + if (type.HasProperties) + CleanProperties (type); + if (type.HasEvents) + CleanEvents (type); + + if (type.HasNestedTypes) + foreach (var nested in type.NestedTypes) + CleanType (nested); + } + + static MethodDefinition CheckMethod (TypeDefinition type, MethodDefinition method) + { + if (method == null) + return null; + + return type.Methods.Contains (method) ? method : null; + } + + static void CleanEvents (TypeDefinition type) + { + var events = type.Events; + + for (int i = 0; i < events.Count; i++) { + var evt = events [i]; + evt.AddMethod = CheckMethod (type, evt.AddMethod); + evt.InvokeMethod = CheckMethod (type, evt.InvokeMethod); + evt.RemoveMethod = CheckMethod (type, evt.RemoveMethod); + + if (!IsEventUsed (evt)) + events.RemoveAt (i--); + } + } + + static bool IsEventUsed (EventDefinition evt) + { + return evt.AddMethod != null || evt.InvokeMethod != null || evt.RemoveMethod != null; + } + + static void CleanProperties (TypeDefinition type) + { + var properties = type.Properties; + + for (int i = 0; i < properties.Count; i++) { + var prop = properties [i]; + prop.GetMethod = CheckMethod (type, prop.GetMethod); + prop.SetMethod = CheckMethod (type, prop.SetMethod); + + if (!IsPropertyUsed (prop)) + properties.RemoveAt (i--); + } + } + + static bool IsPropertyUsed (PropertyDefinition prop) + { + return prop.GetMethod != null || prop.SetMethod != null; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/IStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/IStep.cs new file mode 100644 index 000000000000..c01ef1e6b3fa --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/IStep.cs @@ -0,0 +1,34 @@ +// +// IStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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 Mono.Linker.Steps { + + public interface IStep { + void Process (LinkContext context); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs new file mode 100644 index 000000000000..cd336a66302f --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs @@ -0,0 +1,103 @@ +// +// LoadI18nAssemblies.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Linq; +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class LoadI18nAssemblies : BaseStep { + + static readonly byte [] _pktoken = new byte [] {0x07, 0x38, 0xeb, 0x9f, 0x13, 0x2e, 0xd7, 0x56}; + + I18nAssemblies _assemblies; + + public LoadI18nAssemblies (I18nAssemblies assemblies) + { + _assemblies = assemblies; + } + + protected override bool ConditionToProcess () + { + return _assemblies != I18nAssemblies.None && + Context.GetAssemblies ().FirstOrDefault (a => a.Name.Name == "mscorlib")?.MainModule.GetType ("System.MonoType") != null; + } + + protected override void Process() + { + LoadAssembly (GetAssemblyName (I18nAssemblies.Base)); + + LoadI18nAssembly (I18nAssemblies.CJK); + LoadI18nAssembly (I18nAssemblies.MidEast); + LoadI18nAssembly (I18nAssemblies.Other); + LoadI18nAssembly (I18nAssemblies.Rare); + LoadI18nAssembly (I18nAssemblies.West); + } + + bool ShouldCopyAssembly (I18nAssemblies current) + { + return (current & _assemblies) != 0; + } + + void LoadI18nAssembly (I18nAssemblies asm) + { + if (!ShouldCopyAssembly (asm)) + return; + + AssemblyNameReference name = GetAssemblyName (asm); + LoadAssembly (name); + } + + void LoadAssembly (AssemblyNameReference name) + { + AssemblyDefinition assembly = Context.Resolve (name); + Context.Annotations.SetAction (assembly, AssemblyAction.Copy); + ResolveFromAssemblyStep.ProcessLibrary (Context, assembly, ResolveFromAssemblyStep.RootVisibility.Any); + } + + AssemblyNameReference GetAssemblyName (I18nAssemblies assembly) + { + AssemblyNameReference name = new AssemblyNameReference ("I18N", GetCorlibVersion ()); + if (assembly != I18nAssemblies.Base) + name.Name += "." + assembly; + + name.PublicKeyToken = _pktoken; + return name; + } + + Version GetCorlibVersion () + { + foreach (AssemblyDefinition assembly in Context.GetAssemblies ()) + if (assembly.Name.Name == "mscorlib") + return assembly.Name.Version; + + return new Version (); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs new file mode 100644 index 000000000000..5cd56d3795dd --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs @@ -0,0 +1,61 @@ +// +// LoadReferencesStep.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Collections.Generic; + +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class LoadReferencesStep : BaseStep { + + readonly HashSet references = new HashSet (); + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + ProcessReferences (assembly); + } + + protected void ProcessReferences (AssemblyDefinition assembly) + { + if (!references.Add (assembly.Name)) + return; + + Context.RegisterAssembly (assembly); + + foreach (AssemblyDefinition referenceDefinition in Context.ResolveReferences (assembly)) { + try { + ProcessReferences (referenceDefinition); + } catch (Exception ex) { + throw new LoadException (string.Format ("Error while processing references of '{0}'", assembly.FullName), ex); + } + } + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs new file mode 100644 index 000000000000..55bd31187c80 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs @@ -0,0 +1,3357 @@ +// +// MarkStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// (C) 2007 Novell, 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.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text.RegularExpressions; + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +namespace Mono.Linker.Steps { + + public partial class MarkStep : IStep { + + protected LinkContext _context; + protected Queue _methods; + protected List _virtual_methods; + protected Queue _assemblyLevelAttributes; + protected Queue _lateMarkedAttributes; + protected List _typesWithInterfaces; + protected List _unreachableBodies; + + public MarkStep () + { + _methods = new Queue (); + _virtual_methods = new List (); + _assemblyLevelAttributes = new Queue (); + _lateMarkedAttributes = new Queue (); + _typesWithInterfaces = new List (); + _unreachableBodies = new List (); + } + + public AnnotationStore Annotations => _context.Annotations; + public Tracer Tracer => _context.Tracer; + + public virtual void Process (LinkContext context) + { + _context = context; + + Initialize (); + Process (); + Complete (); + } + + void Initialize () + { + foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) + InitializeAssembly (assembly); + } + + protected virtual void InitializeAssembly (AssemblyDefinition assembly) + { + Tracer.Push (assembly); + try { + switch (_context.Annotations.GetAction (assembly)) { + case AssemblyAction.Copy: + case AssemblyAction.Save: + MarkEntireAssembly (assembly); + break; + case AssemblyAction.Link: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + MarkAssembly (assembly); + + foreach (TypeDefinition type in assembly.MainModule.Types) + InitializeType (type); + + break; + } + } finally { + Tracer.Pop (); + } + } + + void Complete () + { + foreach (var body in _unreachableBodies) { + Annotations.SetAction (body.Method, MethodAction.ConvertToThrow); + } + } + + void InitializeType (TypeDefinition type) + { + if (type.HasNestedTypes) { + foreach (var nested in type.NestedTypes) + InitializeType (nested); + } + + if (!Annotations.IsMarked (type)) + return; + + MarkType (type); + + if (type.HasFields) + InitializeFields (type); + if (type.HasMethods) + InitializeMethods (type.Methods); + } + + protected bool IsFullyPreserved (TypeDefinition type) + { + if (Annotations.TryGetPreserve (type, out TypePreserve preserve) && preserve == TypePreserve.All) + return true; + + switch (Annotations.GetAction (type.Module.Assembly)) { + case AssemblyAction.Save: + case AssemblyAction.Copy: + case AssemblyAction.CopyUsed: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + return true; + } + + return false; + } + + void InitializeFields (TypeDefinition type) + { + foreach (FieldDefinition field in type.Fields) + if (Annotations.IsMarked (field)) + MarkField (field); + } + + void InitializeMethods (Collection methods) + { + foreach (MethodDefinition method in methods) + if (Annotations.IsMarked (method)) + EnqueueMethod (method); + } + + void MarkEntireType (TypeDefinition type) + { + if (type.HasNestedTypes) { + foreach (TypeDefinition nested in type.NestedTypes) + MarkEntireType (nested); + } + + Annotations.Mark (type); + MarkCustomAttributes (type); + MarkTypeSpecialCustomAttributes (type); + + if (type.HasInterfaces) { + foreach (InterfaceImplementation iface in type.Interfaces) { + MarkInterfaceImplementation (iface); + } + } + + MarkGenericParameterProvider (type); + + if (type.HasFields) { + foreach (FieldDefinition field in type.Fields) { + MarkField (field); + } + } + + if (type.HasMethods) { + foreach (MethodDefinition method in type.Methods) { + Annotations.Mark (method); + Annotations.SetAction (method, MethodAction.ForceParse); + EnqueueMethod (method); + } + } + + if (type.HasProperties) { + foreach (var property in type.Properties) { + MarkProperty (property); + } + } + + if (type.HasEvents) { + foreach (var ev in type.Events) { + MarkEvent (ev); + } + } + } + + void Process () + { + while (ProcessPrimaryQueue () || ProcessLazyAttributes () || ProcessLateMarkedAttributes ()) + + // deal with [TypeForwardedTo] pseudo-attributes + foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) { + if (!assembly.MainModule.HasExportedTypes) + continue; + + foreach (var exported in assembly.MainModule.ExportedTypes) { + bool isForwarder = exported.IsForwarder; + var declaringType = exported.DeclaringType; + while (!isForwarder && (declaringType != null)) { + isForwarder = declaringType.IsForwarder; + declaringType = declaringType.DeclaringType; + } + + if (!isForwarder) + continue; + TypeDefinition type = exported.Resolve (); + if (type == null) + continue; + if (!Annotations.IsMarked (type)) + continue; + Tracer.Push (type); + try { + _context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule); + } finally { + Tracer.Pop (); + } + } + } + } + + bool ProcessPrimaryQueue () + { + if (QueueIsEmpty ()) + return false; + + while (!QueueIsEmpty ()) { + ProcessQueue (); + ProcessVirtualMethods (); + ProcessMarkedTypesWithInterfaces (); + ProcessPendingBodies (); + DoAdditionalProcessing (); + } + + return true; + } + + void ProcessQueue () + { + while (!QueueIsEmpty ()) { + MethodDefinition method = _methods.Dequeue (); + Tracer.Push (method); + try { + ProcessMethod (method); + } catch (Exception e) { + throw new MarkException (string.Format ("Error processing method: '{0}' in assembly: '{1}'", method.FullName, method.Module.Name), e, method); + } finally { + Tracer.Pop (); + } + } + } + + bool QueueIsEmpty () + { + return _methods.Count == 0; + } + + protected virtual void EnqueueMethod (MethodDefinition method) + { + _methods.Enqueue (method); + } + + void ProcessVirtualMethods () + { + foreach (MethodDefinition method in _virtual_methods) { + Tracer.Push (method); + ProcessVirtualMethod (method); + Tracer.Pop (); + } + } + + void ProcessMarkedTypesWithInterfaces () + { + // We may mark an interface type later on. Which means we need to reprocess any time with one or more interface implementations that have not been marked + // and if an interface type is found to be marked and implementation is not marked, then we need to mark that implementation + + // copy the data to avoid modified while enumerating error potential, which can happen under certain conditions. + var typesWithInterfaces = _typesWithInterfaces.ToArray (); + + foreach (var type in typesWithInterfaces) { + // Exception, types that have not been flagged as instantiated yet. These types may not need their interfaces even if the + // interface type is marked + if (!Annotations.IsInstantiated (type)) + continue; + + MarkInterfaceImplementations (type); + } + } + + void ProcessPendingBodies () + { + for (int i = 0; i < _unreachableBodies.Count; i++) { + var body = _unreachableBodies [i]; + if (Annotations.IsInstantiated (body.Method.DeclaringType)) { + MarkMethodBody (body); + _unreachableBodies.RemoveAt (i--); + } + } + } + + void ProcessVirtualMethod (MethodDefinition method) + { + var overrides = Annotations.GetOverrides (method); + if (overrides == null) + return; + + foreach (OverrideInformation @override in overrides) + ProcessOverride (@override); + } + + void ProcessOverride (OverrideInformation overrideInformation) + { + var method = overrideInformation.Override; + var @base = overrideInformation.Base; + if (!Annotations.IsMarked (method.DeclaringType)) + return; + + if (Annotations.IsProcessed (method)) + return; + + if (Annotations.IsMarked (method)) + return; + + var isInstantiated = Annotations.IsInstantiated (method.DeclaringType); + + // We don't need to mark overrides until it is possible that the type could be instantiated + // Note : The base type is interface check should be removed once we have base type sweeping + if (IsInterfaceOverrideThatDoesNotNeedMarked (overrideInformation, isInstantiated)) + return; + + if (!isInstantiated && !@base.IsAbstract && _context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval)) + return; + + MarkMethod (method); + ProcessVirtualMethod (method); + } + + bool IsInterfaceOverrideThatDoesNotNeedMarked (OverrideInformation overrideInformation, bool isInstantiated) + { + if (!overrideInformation.IsOverrideOfInterfaceMember || isInstantiated) + return false; + + if (overrideInformation.MatchingInterfaceImplementation != null) + return !Annotations.IsMarked (overrideInformation.MatchingInterfaceImplementation); + + var interfaceType = overrideInformation.InterfaceType; + var overrideDeclaringType = overrideInformation.Override.DeclaringType; + + if (!IsInterfaceImplementationMarked (overrideDeclaringType, interfaceType)) { + var derivedInterfaceTypes = Annotations.GetDerivedInterfacesForInterface (interfaceType); + + // There are no derived interface types that could be marked, it's safe to skip marking this override + if (derivedInterfaceTypes == null) + return true; + + // If none of the other interfaces on the type that implement the interface from the @base type are marked, then it's safe to skip + // marking this override + if (!derivedInterfaceTypes.Any (d => IsInterfaceImplementationMarked (overrideDeclaringType, d))) + return true; + } + + return false; + } + + bool IsInterfaceImplementationMarked (TypeDefinition type, TypeDefinition interfaceType) + { + return type.HasInterface (@interfaceType, out InterfaceImplementation implementation) && Annotations.IsMarked (implementation); + } + + void MarkMarshalSpec (IMarshalInfoProvider spec) + { + if (!spec.HasMarshalInfo) + return; + + if (spec.MarshalInfo is CustomMarshalInfo marshaler) + MarkType (marshaler.ManagedType); + } + + void MarkCustomAttributes (ICustomAttributeProvider provider) + { + if (!provider.HasCustomAttributes) + return; + + bool markOnUse = _context.KeepUsedAttributeTypesOnly && Annotations.GetAction (GetAssemblyFromCustomAttributeProvider (provider)) == AssemblyAction.Link; + + Tracer.Push (provider); + try { + foreach (CustomAttribute ca in provider.CustomAttributes) { + if (IsUserDependencyMarker (ca.AttributeType) && provider is MemberReference mr) { + MarkUserDependency (mr, ca); + + if (_context.KeepDependencyAttributes) { + MarkCustomAttribute (ca); + continue; + } + + if (Annotations.GetAction (mr.Module.Assembly) == AssemblyAction.Link) + continue; + } + + if (markOnUse) { + _lateMarkedAttributes.Enqueue (new AttributeProviderPair (ca, provider)); + continue; + } + + MarkCustomAttribute (ca); + MarkSpecialCustomAttributeDependencies (ca); + } + } finally { + Tracer.Pop (); + } + } + + static AssemblyDefinition GetAssemblyFromCustomAttributeProvider (ICustomAttributeProvider provider) + { + return provider switch { + MemberReference mr => mr.Module.Assembly, + AssemblyDefinition ad => ad, + ModuleDefinition md => md.Assembly, + InterfaceImplementation ii => ii.InterfaceType.Module.Assembly, + GenericParameterConstraint gpc => gpc.ConstraintType.Module.Assembly, + ParameterDefinition pd => pd.ParameterType.Module.Assembly, + MethodReturnType mrt => mrt.ReturnType.Module.Assembly, + _ => throw new NotImplementedException (provider.GetType ().ToString ()), + }; + } + + protected virtual bool IsUserDependencyMarker (TypeReference type) + { + return PreserveDependencyLookupStep.IsPreserveDependencyAttribute (type); + } + + protected virtual void MarkUserDependency (MemberReference context, CustomAttribute ca) + { + if (ca.HasProperties && ca.Properties [0].Name == "Condition") { + var condition = ca.Properties [0].Argument.Value as string; + switch (condition) { + case "": + case null: + break; + case "DEBUG": + if (!_context.KeepMembersForDebugger) + return; + + break; + default: + // Don't have yet a way to match the general condition so everything is excluded + return; + } + } + + AssemblyDefinition assembly; + var args = ca.ConstructorArguments; + if (args.Count >= 3 && args [2].Value is string assemblyName) { + if (!_context.Resolver.AssemblyCache.TryGetValue (assemblyName, out assembly)) { + _context.LogMessage (MessageImportance.Low, $"Could not resolve '{assemblyName}' assembly dependency"); + return; + } + } else { + assembly = null; + } + + TypeDefinition td; + if (args.Count >= 2 && args [1].Value is string typeName) { + td = FindType (assembly ?? context.Module.Assembly, typeName); + + if (td == null) { + _context.LogMessage (MessageImportance.Low, $"Could not resolve '{typeName}' type dependency"); + return; + } + } else { + td = context.DeclaringType.Resolve (); + } + + string member = null; + string[] signature = null; + if (args.Count >= 1 && args [0].Value is string memberSignature) { + memberSignature = memberSignature.Replace (" ", ""); + var sign_start = memberSignature.IndexOf ('('); + var sign_end = memberSignature.LastIndexOf (')'); + if (sign_start > 0 && sign_end > sign_start) { + var parameters = memberSignature.Substring (sign_start + 1, sign_end - sign_start - 1); + signature = string.IsNullOrEmpty (parameters) ? Array.Empty () : parameters.Split (','); + member = memberSignature.Substring (0, sign_start); + } else { + member = memberSignature; + } + } + + if (member == "*") { + MarkEntireType (td); + return; + } + + if (MarkDependencyMethod (td, member, signature)) + return; + + if (MarkDependencyField (td, member)) + return; + + _context.LogMessage (MessageImportance.High, $"Could not resolve dependency member '{member}' declared in type '{td.FullName}'"); + } + + static TypeDefinition FindType (AssemblyDefinition assembly, string fullName) + { + fullName = fullName.ToCecilName (); + + var type = assembly.MainModule.GetType (fullName); + return type?.Resolve (); + } + + bool MarkDependencyMethod (TypeDefinition type, string name, string[] signature) + { + bool marked = false; + + int arity_marker = name.IndexOf ('`'); + if (arity_marker < 1 || !int.TryParse (name.Substring (arity_marker + 1), out int arity)) { + arity = 0; + } else { + name = name.Substring (0, arity_marker); + } + + foreach (var m in type.Methods) { + if (m.Name != name) + continue; + + if (m.GenericParameters.Count != arity) + continue; + + if (signature == null) { + MarkIndirectlyCalledMethod (m); + marked = true; + continue; + } + + var mp = m.Parameters; + if (mp.Count != signature.Length) + continue; + + int i = 0; + for (; i < signature.Length; ++i) { + if (mp [i].ParameterType.FullName != signature [i].Trim ().ToCecilName ()) { + i = -1; + break; + } + } + + if (i < 0) + continue; + + MarkIndirectlyCalledMethod (m); + marked = true; + } + + return marked; + } + + bool MarkDependencyField (TypeDefinition type, string name) + { + foreach (var f in type.Fields) { + if (f.Name == name) { + MarkField (f); + return true; + } + } + + return false; + } + + void LazyMarkCustomAttributes (ICustomAttributeProvider provider, AssemblyDefinition assembly) + { + if (!provider.HasCustomAttributes) + return; + + foreach (CustomAttribute ca in provider.CustomAttributes) + _assemblyLevelAttributes.Enqueue (new AttributeProviderPair (ca, assembly)); + } + + protected virtual void MarkCustomAttribute (CustomAttribute ca) + { + Tracer.Push ((object)ca.AttributeType ?? (object)ca); + try { + Annotations.Mark (ca); + MarkMethod (ca.Constructor); + + MarkCustomAttributeArguments (ca); + + TypeReference constructor_type = ca.Constructor.DeclaringType; + TypeDefinition type = constructor_type.Resolve (); + + if (type == null) { + HandleUnresolvedType (constructor_type); + return; + } + + MarkCustomAttributeProperties (ca, type); + MarkCustomAttributeFields (ca, type); + } finally { + Tracer.Pop (); + } + } + + protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca, ICustomAttributeProvider provider) + { + var attr_type = ca.AttributeType; + + if (_context.KeepUsedAttributeTypesOnly) { + switch (attr_type.FullName) { + // These are required by the runtime + case "System.ThreadStaticAttribute": + case "System.ContextStaticAttribute": + case "System.Runtime.CompilerServices.IsByRefLikeAttribute": + return true; + // Attributes related to `fixed` keyword used to declare fixed length arrays + case "System.Runtime.CompilerServices.FixedBufferAttribute": + return true; + case "System.Runtime.InteropServices.InterfaceTypeAttribute": + case "System.Runtime.InteropServices.GuidAttribute": + case "System.Runtime.CompilerServices.InternalsVisibleToAttribute": + return true; + } + + if (!Annotations.IsMarked (attr_type.Resolve ())) + return false; + } + + return true; + } + + protected virtual bool ShouldMarkTypeStaticConstructor (TypeDefinition type) + { + if (Annotations.HasPreservedStaticCtor (type)) + return false; + + if (type.IsBeforeFieldInit && _context.IsOptimizationEnabled (CodeOptimizations.BeforeFieldInit)) + return false; + + return true; + } + + protected void MarkStaticConstructor (TypeDefinition type) + { + if (MarkMethodIf (type.Methods, IsNonEmptyStaticConstructor) != null) + Annotations.SetPreservedStaticCtor (type); + } + + protected virtual bool ShouldMarkTopLevelCustomAttribute (AttributeProviderPair app, MethodDefinition resolvedConstructor) + { + var ca = app.Attribute; + + if (!ShouldMarkCustomAttribute (app.Attribute, app.Provider)) + return false; + + // If an attribute's module has not been marked after processing all types in all assemblies and the attribute itself has not been marked, + // then surely nothing is using this attribute and there is no need to mark it + if (!Annotations.IsMarked (resolvedConstructor.Module) && + !Annotations.IsMarked (ca.AttributeType) && + Annotations.GetAction (resolvedConstructor.Module.Assembly) == AssemblyAction.Link) + return false; + + if (ca.Constructor.DeclaringType.Namespace == "System.Diagnostics") { + string attributeName = ca.Constructor.DeclaringType.Name; + if (attributeName == "DebuggerDisplayAttribute" || attributeName == "DebuggerTypeProxyAttribute") { + var displayTargetType = GetDebuggerAttributeTargetType (app.Attribute, (AssemblyDefinition) app.Provider); + if (displayTargetType == null || !Annotations.IsMarked (displayTargetType)) + return false; + } + } + + return true; + } + + protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider) + { + // most security declarations are removed (if linked) but user code might still have some + // and if the attributes references types then they need to be marked too + if ((provider == null) || !provider.HasSecurityDeclarations) + return; + + foreach (var sd in provider.SecurityDeclarations) + MarkSecurityDeclaration (sd); + } + + protected virtual void MarkSecurityDeclaration (SecurityDeclaration sd) + { + if (!sd.HasSecurityAttributes) + return; + + foreach (var sa in sd.SecurityAttributes) + MarkSecurityAttribute (sa); + } + + protected virtual void MarkSecurityAttribute (SecurityAttribute sa) + { + TypeReference security_type = sa.AttributeType; + TypeDefinition type = security_type.Resolve (); + if (type == null) { + HandleUnresolvedType (security_type); + return; + } + + MarkType (security_type); + MarkSecurityAttributeProperties (sa, type); + MarkSecurityAttributeFields (sa, type); + } + + protected void MarkSecurityAttributeProperties (SecurityAttribute sa, TypeDefinition attribute) + { + if (!sa.HasProperties) + return; + + foreach (var named_argument in sa.Properties) + MarkCustomAttributeProperty (named_argument, attribute); + } + + protected void MarkSecurityAttributeFields (SecurityAttribute sa, TypeDefinition attribute) + { + if (!sa.HasFields) + return; + + foreach (var named_argument in sa.Fields) + MarkCustomAttributeField (named_argument, attribute); + } + + protected void MarkCustomAttributeProperties (CustomAttribute ca, TypeDefinition attribute) + { + if (!ca.HasProperties) + return; + + foreach (var named_argument in ca.Properties) + MarkCustomAttributeProperty (named_argument, attribute); + } + + protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute) + { + PropertyDefinition property = GetProperty (attribute, namedArgument.Name); + Tracer.Push (property); + if (property != null) + MarkMethod (property.SetMethod); + + MarkCustomAttributeArgument (namedArgument.Argument); + Tracer.Pop (); + } + + PropertyDefinition GetProperty (TypeDefinition type, string propertyname) + { + while (type != null) { + PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname); + if (property != null) + return property; + + type = type.BaseType?.Resolve (); + } + + return null; + } + + protected void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition attribute) + { + if (!ca.HasFields) + return; + + foreach (var named_argument in ca.Fields) + MarkCustomAttributeField (named_argument, attribute); + } + + protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute) + { + FieldDefinition field = GetField (attribute, namedArgument.Name); + if (field != null) + MarkField (field); + + MarkCustomAttributeArgument (namedArgument.Argument); + } + + FieldDefinition GetField (TypeDefinition type, string fieldname) + { + while (type != null) { + FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname); + if (field != null) + return field; + + type = type.BaseType?.Resolve (); + } + + return null; + } + + MethodDefinition GetMethodWithNoParameters (TypeDefinition type, string methodname) + { + while (type != null) { + MethodDefinition method = type.Methods.FirstOrDefault (m => m.Name == methodname && !m.HasParameters); + if (method != null) + return method; + + type = type.BaseType.Resolve (); + } + + return null; + } + + void MarkCustomAttributeArguments (CustomAttribute ca) + { + if (!ca.HasConstructorArguments) + return; + + foreach (var argument in ca.ConstructorArguments) + MarkCustomAttributeArgument (argument); + } + + void MarkCustomAttributeArgument (CustomAttributeArgument argument) + { + var at = argument.Type; + + if (at.IsArray) { + var et = at.GetElementType (); + + MarkType (et); + if (argument.Value == null) + return; + + foreach (var caa in (CustomAttributeArgument [])argument.Value) + MarkCustomAttributeArgument (caa); + + return; + } + + if (at.Namespace == "System") { + switch (at.Name) { + case "Type": + MarkType (argument.Type); + MarkType ((TypeReference)argument.Value); + return; + + case "Object": + var boxed_value = (CustomAttributeArgument)argument.Value; + MarkType (boxed_value.Type); + MarkCustomAttributeArgument (boxed_value); + return; + } + } + } + + protected bool CheckProcessed (IMetadataTokenProvider provider) + { + if (Annotations.IsProcessed (provider)) + return true; + + Annotations.Processed (provider); + return false; + } + + protected void MarkAssembly (AssemblyDefinition assembly) + { + if (CheckProcessed (assembly)) + return; + + ProcessModule (assembly); + + MarkAssemblyCustomAttributes (assembly); + + MarkSecurityDeclarations (assembly); + + foreach (ModuleDefinition module in assembly.Modules) + LazyMarkCustomAttributes (module, assembly); + } + + void MarkEntireAssembly (AssemblyDefinition assembly) + { + MarkCustomAttributes (assembly); + MarkCustomAttributes (assembly.MainModule); + + if (assembly.MainModule.HasExportedTypes) { + // TODO: This needs more work accross all steps + } + + foreach (TypeDefinition type in assembly.MainModule.Types) + MarkEntireType (type); + } + + void ProcessModule (AssemblyDefinition assembly) + { + // Pre-mark if there is any methods as they need to be executed + // at assembly load time + foreach (TypeDefinition type in assembly.MainModule.Types) + { + if (type.Name == "" && type.HasMethods) + { + MarkType (type); + break; + } + } + } + + bool ProcessLazyAttributes () + { + if (Annotations.HasMarkedAnyIndirectlyCalledMethods () && MarkDisablePrivateReflectionAttribute ()) + return true; + + var startingQueueCount = _assemblyLevelAttributes.Count; + if (startingQueueCount == 0) + return false; + + var skippedItems = new List (); + var markOccurred = false; + + while (_assemblyLevelAttributes.Count != 0) { + var assemblyLevelAttribute = _assemblyLevelAttributes.Dequeue (); + var customAttribute = assemblyLevelAttribute.Attribute; + + var resolved = customAttribute.Constructor.Resolve (); + if (resolved == null) { + HandleUnresolvedMethod (customAttribute.Constructor); + continue; + } + + if (!ShouldMarkTopLevelCustomAttribute (assemblyLevelAttribute, resolved)) { + skippedItems.Add (assemblyLevelAttribute); + continue; + } + + string attributeFullName = customAttribute.Constructor.DeclaringType.FullName; + switch (attributeFullName) { + case "System.Diagnostics.DebuggerDisplayAttribute": + MarkTypeWithDebuggerDisplayAttribute (GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider), customAttribute); + break; + case "System.Diagnostics.DebuggerTypeProxyAttribute": + MarkTypeWithDebuggerTypeProxyAttribute (GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider), customAttribute); + break; + } + + markOccurred = true; + MarkCustomAttribute (customAttribute); + } + + // requeue the items we skipped in case we need to make another pass + foreach (var item in skippedItems) + _assemblyLevelAttributes.Enqueue (item); + + return markOccurred; + } + + bool ProcessLateMarkedAttributes () + { + var startingQueueCount = _lateMarkedAttributes.Count; + if (startingQueueCount == 0) + return false; + + var skippedItems = new List (); + var markOccurred = false; + + while (_lateMarkedAttributes.Count != 0) { + var attributeProviderPair = _lateMarkedAttributes.Dequeue (); + var customAttribute = attributeProviderPair.Attribute; + + var resolved = customAttribute.Constructor.Resolve (); + if (resolved == null) { + HandleUnresolvedMethod (customAttribute.Constructor); + continue; + } + + if (!ShouldMarkCustomAttribute (customAttribute, attributeProviderPair.Provider)) { + skippedItems.Add (attributeProviderPair); + continue; + } + + markOccurred = true; + MarkCustomAttribute (customAttribute); + MarkSpecialCustomAttributeDependencies (customAttribute); + } + + // requeue the items we skipped in case we need to make another pass + foreach (var item in skippedItems) + _lateMarkedAttributes.Enqueue (item); + + return markOccurred; + } + + protected void MarkField (FieldReference reference) + { + if (reference.DeclaringType is GenericInstanceType) + MarkType (reference.DeclaringType); + + FieldDefinition field = reference.Resolve (); + + if (field == null) { + HandleUnresolvedField (reference); + return; + } + + MarkField (field); + } + + void MarkField (FieldDefinition field) + { + if (CheckProcessed (field)) + return; + + MarkType (field.DeclaringType); + MarkType (field.FieldType); + MarkCustomAttributes (field); + MarkMarshalSpec (field); + DoAdditionalFieldProcessing (field); + + var parent = field.DeclaringType; + if (!Annotations.HasPreservedStaticCtor (parent)) + MarkStaticConstructor (parent); + + if (Annotations.HasSubstitutedInit (field)) { + Annotations.SetPreservedStaticCtor (parent); + Annotations.SetSubstitutedInit (parent); + } + + Annotations.Mark (field); + } + + protected virtual bool IgnoreScope (IMetadataScope scope) + { + AssemblyDefinition assembly = ResolveAssembly (scope); + return Annotations.GetAction (assembly) != AssemblyAction.Link; + } + + void MarkScope (IMetadataScope scope) + { + if (scope is IMetadataTokenProvider provider) + Annotations.Mark (provider); + } + + protected virtual void MarkSerializable (TypeDefinition type) + { + MarkDefaultConstructor (type); + MarkMethodsIf (type.Methods, IsSpecialSerializationConstructor); + } + + protected virtual TypeDefinition MarkType (TypeReference reference) + { + if (reference == null) + return null; + + reference = GetOriginalType (reference); + + if (reference is FunctionPointerType) + return null; + + if (reference is GenericParameter) + return null; + +// if (IgnoreScope (reference.Scope)) +// return null; + + TypeDefinition type = reference.Resolve (); + + if (type == null) { + HandleUnresolvedType (reference); + return null; + } + + if (CheckProcessed (type)) + return null; + + Tracer.Push (type); + + MarkScope (type.Scope); + MarkType (type.BaseType); + MarkType (type.DeclaringType); + MarkCustomAttributes (type); + MarkSecurityDeclarations (type); + + if (type.IsMulticastDelegate ()) { + MarkMulticastDelegate (type); + } + + if (type.IsSerializable ()) + MarkSerializable (type); + + if (!_context.IsFeatureExcluded ("etw") && BCL.EventTracingForWindows.IsEventSourceImplementation (type, _context)) { + MarkEventSourceProviders (type); + } + + MarkTypeSpecialCustomAttributes (type); + + MarkGenericParameterProvider (type); + + // keep fields for value-types and for classes with LayoutKind.Sequential or Explicit + if (type.IsValueType || !type.IsAutoLayout) + MarkFields (type, type.IsEnum); + + // There are a number of markings we can defer until later when we know it's possible a reference type could be instantiated + // For example, if no instance of a type exist, then we don't need to mark the interfaces on that type + // However, for some other types there is no benefit to deferring + if (type.IsInterface) { + // There's no benefit to deferring processing of an interface type until we know a type implementing that interface is marked + MarkRequirementsForInstantiatedTypes (type); + } else if (type.IsValueType) { + // Note : Technically interfaces could be removed from value types in some of the same cases as reference types, however, it's harder to know when + // a value type instance could exist. You'd have to track initobj and maybe locals types. Going to punt for now. + MarkRequirementsForInstantiatedTypes (type); + } else if (IsFullyPreserved (type)) { + // Here for a couple reasons: + // * Edge case to cover a scenario where a type has preserve all, implements interfaces, but does not have any instance ctors. + // Normally TypePreserve.All would cause an instance ctor to be marked and that would in turn lead to MarkInterfaceImplementations being called + // Without an instance ctor, MarkInterfaceImplementations is not called and then TypePreserve.All isn't truly respected. + // * If an assembly has the action Copy and had ResolveFromAssemblyStep ran for the assembly, then InitializeType will have led us here + // When the entire assembly is preserved, then all interfaces, base, etc will be preserved on the type, so we need to make sure + // all of these types are marked. For example, if an interface implementation is of a type in another assembly that is linked, + // and there are no other usages of that interface type, then we need to make sure the interface type is still marked because + // this type is going to retain the interface implementation + MarkRequirementsForInstantiatedTypes (type); + } else if (AlwaysMarkTypeAsInstantiated (type)) { + MarkRequirementsForInstantiatedTypes (type); + } + + if (type.HasInterfaces) + _typesWithInterfaces.Add (type); + + if (type.HasMethods) { + MarkMethodsIf (type.Methods, IsVirtualNeededByTypeDueToPreservedScope); + if (ShouldMarkTypeStaticConstructor (type)) + MarkStaticConstructor (type); + + MarkMethodsIf (type.Methods, HasSerializationAttribute); + } + + DoAdditionalTypeProcessing (type); + + Tracer.Pop (); + + Annotations.Mark (type); + + ApplyPreserveInfo (type); + + return type; + } + + // Allow subclassers to mark additional things in the main processing loop + protected virtual void DoAdditionalProcessing () + { + } + + // Allow subclassers to mark additional things + protected virtual void DoAdditionalTypeProcessing (TypeDefinition type) + { + } + + // Allow subclassers to mark additional things + protected virtual void DoAdditionalFieldProcessing (FieldDefinition field) + { + } + + // Allow subclassers to mark additional things + protected virtual void DoAdditionalPropertyProcessing (PropertyDefinition property) + { + } + + // Allow subclassers to mark additional things + protected virtual void DoAdditionalEventProcessing (EventDefinition evt) + { + } + + // Allow subclassers to mark additional things + protected virtual void DoAdditionalInstantiatedTypeProcessing (TypeDefinition type) + { + } + + void MarkAssemblyCustomAttributes (AssemblyDefinition assembly) + { + if (!assembly.HasCustomAttributes) + return; + + foreach (CustomAttribute attribute in assembly.CustomAttributes) + _assemblyLevelAttributes.Enqueue (new AttributeProviderPair (attribute, assembly)); + } + + TypeDefinition GetDebuggerAttributeTargetType (CustomAttribute ca, AssemblyDefinition asm) + { + TypeReference targetTypeReference = null; + foreach (var property in ca.Properties) { + if (property.Name == "Target") { + targetTypeReference = (TypeReference) property.Argument.Value; + break; + } + + if (property.Name == "TargetTypeName") { + if (TypeNameParser.TryParseTypeAssemblyQualifiedName ((string) property.Argument.Value, out string typeName, out string assemblyName)) { + if (string.IsNullOrEmpty (assemblyName)) + targetTypeReference = asm.MainModule.GetType (typeName); + else + targetTypeReference = _context.GetAssemblies ().FirstOrDefault (a => a.Name.Name == assemblyName)?.MainModule.GetType (typeName); + } + break; + } + } + + return targetTypeReference?.Resolve (); + } + + void MarkTypeSpecialCustomAttributes (TypeDefinition type) + { + if (!type.HasCustomAttributes) + return; + + foreach (CustomAttribute attribute in type.CustomAttributes) { + var attrType = attribute.Constructor.DeclaringType; + switch (attrType.Name) { + case "XmlSchemaProviderAttribute" when attrType.Namespace == "System.Xml.Serialization": + MarkXmlSchemaProvider (type, attribute); + break; + case "DebuggerDisplayAttribute" when attrType.Namespace == "System.Diagnostics": + MarkTypeWithDebuggerDisplayAttribute (type, attribute); + break; + case "DebuggerTypeProxyAttribute" when attrType.Namespace == "System.Diagnostics": + MarkTypeWithDebuggerTypeProxyAttribute (type, attribute); + break; + case "EventDataAttribute" when attrType.Namespace == "System.Diagnostics.Tracing": + MarkMethodsIf (type.Methods, MethodDefinitionExtensions.IsPublicInstancePropertyMethod); + break; + case "TypeDescriptionProviderAttribute" when attrType.Namespace == "System.ComponentModel": + MarkTypeConverterLikeDependency (attribute, l => l.IsDefaultConstructor ()); + break; + } + } + } + + // + // Used for known framework attributes which can be applied to any element + // + bool MarkSpecialCustomAttributeDependencies (CustomAttribute ca) + { + var dt = ca.Constructor.DeclaringType; + if (dt.Name == "TypeConverterAttribute" && dt.Namespace == "System.ComponentModel") { + MarkTypeConverterLikeDependency (ca, l => + l.IsDefaultConstructor () || + l.Parameters.Count == 1 && l.Parameters [0].ParameterType.IsTypeOf ("System", "Type")); + return true; + } + + return false; + } + + void MarkMethodSpecialCustomAttributes (MethodDefinition method) + { + if (!method.HasCustomAttributes) + return; + + foreach (CustomAttribute attribute in method.CustomAttributes) { + switch (attribute.Constructor.DeclaringType.FullName) { + case "System.Web.Services.Protocols.SoapHeaderAttribute": + MarkSoapHeader (method, attribute); + break; + } + } + } + + void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute) + { + if (TryGetStringArgument (attribute, out string name)) + MarkNamedMethod (type, name); + } + + protected virtual void MarkTypeConverterLikeDependency (CustomAttribute attribute, Func predicate) + { + var args = attribute.ConstructorArguments; + if (args.Count < 1) + return; + + TypeDefinition tdef = null; + switch (attribute.ConstructorArguments [0].Value) { + case string s: + tdef = ResolveFullyQualifiedTypeName (s); + break; + case TypeReference type: + tdef = type.Resolve (); + break; + } + + if (tdef == null) + return; + + MarkMethodsIf (tdef.Methods, predicate); + } + + void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute attribute) + { + if (_context.KeepMembersForDebugger) { + + string displayString = (string) attribute.ConstructorArguments[0].Value; + + Regex regex = new Regex ("{[^{}]+}", RegexOptions.Compiled); + + foreach (Match match in regex.Matches (displayString)) { + // Remove '{' and '}' + string realMatch = match.Value.Substring (1, match.Value.Length - 2); + + // Remove ",nq" suffix if present + // (it asks the expression evaluator to remove the quotes when displaying the final value) + if (Regex.IsMatch(realMatch, @".+,\s*nq")) { + realMatch = realMatch.Substring (0, realMatch.LastIndexOf (',')); + } + + if (realMatch.EndsWith ("()")) { + string methodName = realMatch.Substring (0, realMatch.Length - 2); + MethodDefinition method = GetMethodWithNoParameters (type, methodName); + if (method != null) { + MarkMethod (method); + continue; + } + } else { + FieldDefinition field = GetField (type, realMatch); + if (field != null) { + MarkField (field); + continue; + } + + PropertyDefinition property = GetProperty (type, realMatch); + if (property != null) { + if (property.GetMethod != null) { + MarkMethod (property.GetMethod); + } + if (property.SetMethod != null) { + MarkMethod (property.SetMethod); + } + continue; + } + } + + while (type != null) { + MarkMethods (type); + MarkFields (type, includeStatic: true); + type = type.BaseType?.Resolve (); + } + return; + } + } + } + + void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute) + { + if (_context.KeepMembersForDebugger) { + object constructorArgument = attribute.ConstructorArguments[0].Value; + TypeReference proxyTypeReference = constructorArgument as TypeReference; + if (proxyTypeReference == null) { + if (constructorArgument is string proxyTypeReferenceString) { + proxyTypeReference = type.Module.GetType (proxyTypeReferenceString, runtimeName: true); + } + } + + if (proxyTypeReference == null) { + return; + } + + MarkType (proxyTypeReference); + + TypeDefinition proxyType = proxyTypeReference.Resolve (); + if (proxyType != null) { + MarkMethods (proxyType); + MarkFields (proxyType, includeStatic: true); + } + } + } + + static bool TryGetStringArgument (CustomAttribute attribute, out string argument) + { + argument = null; + + if (attribute.ConstructorArguments.Count < 1) + return false; + + argument = attribute.ConstructorArguments [0].Value as string; + + return argument != null; + } + + protected int MarkNamedMethod (TypeDefinition type, string method_name) + { + if (!type.HasMethods) + return 0; + + int count = 0; + foreach (MethodDefinition method in type.Methods) { + if (method.Name != method_name) + continue; + + MarkMethod (method); + count++; + } + + return count; + } + + void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute) + { + if (!TryGetStringArgument (attribute, out string member_name)) + return; + + MarkNamedField (method.DeclaringType, member_name); + MarkNamedProperty (method.DeclaringType, member_name); + } + + void MarkNamedField (TypeDefinition type, string field_name) + { + if (!type.HasFields) + return; + + foreach (FieldDefinition field in type.Fields) { + if (field.Name != field_name) + continue; + + MarkField (field); + } + } + + void MarkNamedProperty (TypeDefinition type, string property_name) + { + if (!type.HasProperties) + return; + + foreach (PropertyDefinition property in type.Properties) { + if (property.Name != property_name) + continue; + + Tracer.Push (property); + MarkMethod (property.GetMethod); + MarkMethod (property.SetMethod); + Tracer.Pop (); + } + } + + void MarkInterfaceImplementations (TypeDefinition type) + { + if (!type.HasInterfaces) + return; + + foreach (var iface in type.Interfaces) { + // Only mark interface implementations of interface types that have been marked. + // This enables stripping of interfaces that are never used + var resolvedInterfaceType = iface.InterfaceType.Resolve (); + if (resolvedInterfaceType == null) { + HandleUnresolvedType (iface.InterfaceType); + continue; + } + + if (ShouldMarkInterfaceImplementation (type, iface, resolvedInterfaceType)) + MarkInterfaceImplementation (iface); + } + } + + void MarkGenericParameterProvider (IGenericParameterProvider provider) + { + if (!provider.HasGenericParameters) + return; + + foreach (GenericParameter parameter in provider.GenericParameters) + MarkGenericParameter (parameter); + } + + void MarkGenericParameter (GenericParameter parameter) + { + MarkCustomAttributes (parameter); + if (!parameter.HasConstraints) + return; + + foreach (var constraint in parameter.Constraints) { + MarkCustomAttributes (constraint); + MarkType (constraint.ConstraintType); + } + } + + bool IsVirtualNeededByTypeDueToPreservedScope (MethodDefinition method) + { + if (!method.IsVirtual) + return false; + + var base_list = Annotations.GetBaseMethods (method); + if (base_list == null) + return false; + + foreach (MethodDefinition @base in base_list) { + // Just because the type is marked does not mean we need interface methods. + // if the type is never instantiated, interfaces will be removed + if (@base.DeclaringType.IsInterface) + continue; + + // If the type is marked, we need to keep overrides of abstract members defined in assemblies + // that are copied. However, if the base method is virtual, then we don't need to keep the override + // until the type could be instantiated + if (!@base.IsAbstract) + continue; + + if (IgnoreScope (@base.DeclaringType.Scope)) + return true; + + if (IsVirtualNeededByTypeDueToPreservedScope (@base)) + return true; + } + + return false; + } + + bool IsVirtualNeededByInstantiatedTypeDueToPreservedScope (MethodDefinition method) + { + if (!method.IsVirtual) + return false; + + var base_list = Annotations.GetBaseMethods (method); + if (base_list == null) + return false; + + foreach (MethodDefinition @base in base_list) { + if (IgnoreScope (@base.DeclaringType.Scope)) + return true; + + if (IsVirtualNeededByTypeDueToPreservedScope (@base)) + return true; + } + + return false; + } + + static bool IsSpecialSerializationConstructor (MethodDefinition method) + { + if (!method.IsInstanceConstructor ()) + return false; + + var parameters = method.Parameters; + if (parameters.Count != 2) + return false; + + return parameters [0].ParameterType.Name == "SerializationInfo" && + parameters [1].ParameterType.Name == "StreamingContext"; + } + + protected void MarkMethodsIf (Collection methods, Func predicate) + { + foreach (MethodDefinition method in methods) + if (predicate (method)) + MarkMethod (method); + } + + protected MethodDefinition MarkMethodIf (Collection methods, Func predicate) + { + foreach (MethodDefinition method in methods) { + if (predicate (method)) { + return MarkMethod (method); + } + } + + return null; + } + + protected bool MarkDefaultConstructor (TypeDefinition type) + { + if (type?.HasMethods != true) + return false; + + return MarkMethodIf (type.Methods, MethodDefinitionExtensions.IsDefaultConstructor) != null; + } + + static bool IsNonEmptyStaticConstructor (MethodDefinition method) + { + if (!method.IsStaticConstructor ()) + return false; + + if (!method.HasBody || !method.IsIL) + return true; + + if (method.Body.CodeSize != 1) + return true; + + return method.Body.Instructions [0].OpCode.Code != Code.Ret; + } + + static bool HasSerializationAttribute (MethodDefinition method) + { + if (!method.HasCustomAttributes) + return false; + foreach (var ca in method.CustomAttributes) { + var cat = ca.AttributeType; + if (cat.Namespace != "System.Runtime.Serialization") + continue; + switch (cat.Name) { + case "OnDeserializedAttribute": + case "OnDeserializingAttribute": + case "OnSerializedAttribute": + case "OnSerializingAttribute": + return true; + } + } + return false; + } + + protected virtual bool AlwaysMarkTypeAsInstantiated (TypeDefinition td) + { + switch (td.Name) { + // These types are created from native code which means we are unable to track when they are instantiated + // Since these are such foundational types, let's take the easy route and just always assume an instance of one of these + // could exist + case "Delegate": + case "MulticastDelegate": + case "ValueType": + case "Enum": + return td.Namespace == "System"; + } + + return false; + } + + void MarkEventSourceProviders (TypeDefinition td) + { + foreach (var nestedType in td.NestedTypes) { + if (BCL.EventTracingForWindows.IsProviderName (nestedType.Name)) + MarkStaticFields (nestedType); + } + } + + protected virtual void MarkMulticastDelegate (TypeDefinition type) + { + MarkMethodCollection (type.Methods); + } + + TypeDefinition ResolveFullyQualifiedTypeName (string name) + { + if (!TypeNameParser.TryParseTypeAssemblyQualifiedName (name, out string typeName, out string assemblyName)) + return null; + + foreach (var assemblyDefinition in _context.GetAssemblies ()) { + if (assemblyName != null && assemblyDefinition.Name.Name != assemblyName) + continue; + + var foundType = assemblyDefinition.MainModule.GetType (typeName); + if (foundType == null) + continue; + + return foundType; + } + + return null; + } + + protected TypeReference GetOriginalType (TypeReference type) + { + while (type is TypeSpecification) { + if (type is GenericInstanceType git) + MarkGenericArguments (git); + + if (type is IModifierType mod) + MarkModifierType (mod); + + if (type is FunctionPointerType fnptr) { + MarkParameters (fnptr); + MarkType (fnptr.ReturnType); + break; // FunctionPointerType is the original type + } + + type = ((TypeSpecification)type).ElementType; + } + + return type; + } + + void MarkParameters (FunctionPointerType fnptr) + { + if (!fnptr.HasParameters) + return; + + for (int i = 0; i < fnptr.Parameters.Count; i++) + { + MarkType (fnptr.Parameters[i].ParameterType); + } + } + + void MarkModifierType (IModifierType mod) + { + MarkType (mod.ModifierType); + } + + void MarkGenericArguments (IGenericInstance instance) + { + foreach (TypeReference argument in instance.GenericArguments) + MarkType (argument); + + MarkGenericArgumentConstructors (instance); + } + + void MarkGenericArgumentConstructors (IGenericInstance instance) + { + var arguments = instance.GenericArguments; + + var generic_element = GetGenericProviderFromInstance (instance); + if (generic_element == null) + return; + + var parameters = generic_element.GenericParameters; + + if (arguments.Count != parameters.Count) + return; + + for (int i = 0; i < arguments.Count; i++) { + var argument = arguments [i]; + var parameter = parameters [i]; + + if (!parameter.HasDefaultConstructorConstraint) + continue; + + var argument_definition = argument.Resolve (); + MarkDefaultConstructor (argument_definition); + } + } + + static IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance) + { + if (instance is GenericInstanceMethod method) + return method.ElementMethod.Resolve (); + + if (instance is GenericInstanceType type) + return type.ElementType.Resolve (); + + return null; + } + + void ApplyPreserveInfo (TypeDefinition type) + { + ApplyPreserveMethods (type); + + if (!Annotations.TryGetPreserve (type, out TypePreserve preserve)) + return; + + switch (preserve) { + case TypePreserve.All: + MarkFields (type, true); + MarkMethods (type); + break; + case TypePreserve.Fields: + if (!MarkFields (type, true, true)) + _context.LogMessage ($"Type {type.FullName} has no fields to preserve"); + break; + case TypePreserve.Methods: + if (!MarkMethods (type)) + _context.LogMessage ($"Type {type.FullName} has no methods to preserve"); + break; + } + } + + void ApplyPreserveMethods (TypeDefinition type) + { + var list = Annotations.GetPreservedMethods (type); + if (list == null) + return; + + MarkMethodCollection (list); + } + + void ApplyPreserveMethods (MethodDefinition method) + { + var list = Annotations.GetPreservedMethods (method); + if (list == null) + return; + + MarkMethodCollection (list); + } + + protected bool MarkFields (TypeDefinition type, bool includeStatic, bool markBackingFieldsOnlyIfPropertyMarked = false) + { + if (!type.HasFields) + return false; + + foreach (FieldDefinition field in type.Fields) { + if (!includeStatic && field.IsStatic) + continue; + + if (markBackingFieldsOnlyIfPropertyMarked && field.Name.EndsWith (">k__BackingField", StringComparison.Ordinal)) { + // We can't reliably construct the expected property name from the backing field name for all compilers + // because csc shortens the name of the backing field in some cases + // For example: + // Field Name = .Bar>k__BackingField + // Property Name = IFoo.Bar + // + // instead we will search the properties and find the one that makes use of the current backing field + var propertyDefinition = SearchPropertiesForMatchingFieldDefinition (field); + if (propertyDefinition != null && !Annotations.IsMarked (propertyDefinition)) + continue; + } + MarkField (field); + } + + return true; + } + + static PropertyDefinition SearchPropertiesForMatchingFieldDefinition (FieldDefinition field) + { + foreach (var property in field.DeclaringType.Properties) { + var instr = property.GetMethod?.Body?.Instructions; + if (instr == null) + continue; + + foreach (var ins in instr) { + if (ins?.Operand == field) + return property; + } + } + + return null; + } + + protected void MarkStaticFields (TypeDefinition type) + { + if (!type.HasFields) + return; + + foreach (FieldDefinition field in type.Fields) { + if (field.IsStatic) + MarkField (field); + } + } + + protected virtual bool MarkMethods (TypeDefinition type) + { + if (!type.HasMethods) + return false; + + MarkMethodCollection (type.Methods); + return true; + } + + void MarkMethodCollection (IList methods) + { + foreach (MethodDefinition method in methods) + MarkMethod (method); + } + + protected void MarkIndirectlyCalledMethod (MethodDefinition method) + { + MarkMethod (method); + Annotations.MarkIndirectlyCalledMethod (method); + } + + protected virtual MethodDefinition MarkMethod (MethodReference reference) + { + reference = GetOriginalMethod (reference); + + if (reference.DeclaringType is ArrayType) + return null; + + Tracer.Push (reference); + if (reference.DeclaringType is GenericInstanceType) + MarkType (reference.DeclaringType); + +// if (IgnoreScope (reference.DeclaringType.Scope)) +// return; + + MethodDefinition method = reference.Resolve (); + + try { + if (method == null) { + HandleUnresolvedMethod (reference); + return null; + } + + if (Annotations.GetAction (method) == MethodAction.Nothing) + Annotations.SetAction (method, MethodAction.Parse); + + EnqueueMethod (method); + } finally { + Tracer.Pop (); + } + Tracer.AddDependency (method); + + return method; + } + + AssemblyDefinition ResolveAssembly (IMetadataScope scope) + { + AssemblyDefinition assembly = _context.Resolve (scope); + MarkAssembly (assembly); + return assembly; + } + + protected MethodReference GetOriginalMethod (MethodReference method) + { + while (method is MethodSpecification) { + if (method is GenericInstanceMethod gim) + MarkGenericArguments (gim); + + method = ((MethodSpecification) method).ElementMethod; + } + + return method; + } + + protected virtual void ProcessMethod (MethodDefinition method) + { + if (CheckProcessed (method)) + return; + + Tracer.Push (method); + MarkType (method.DeclaringType); + MarkCustomAttributes (method); + MarkSecurityDeclarations (method); + + MarkGenericParameterProvider (method); + + if (ShouldMarkAsInstancePossible (method)) + MarkRequirementsForInstantiatedTypes (method.DeclaringType); + + if (method.IsConstructor) { + if (!Annotations.ProcessSatelliteAssemblies && KnownMembers.IsSatelliteAssemblyMarker (method)) + Annotations.ProcessSatelliteAssemblies = true; + } else if (method.IsPropertyMethod ()) + MarkProperty (method.GetProperty ()); + else if (method.IsEventMethod ()) + MarkEvent (method.GetEvent ()); + + if (method.HasParameters) { + foreach (ParameterDefinition pd in method.Parameters) { + MarkType (pd.ParameterType); + MarkCustomAttributes (pd); + MarkMarshalSpec (pd); + } + } + + if (method.HasOverrides) { + foreach (MethodReference ov in method.Overrides) { + MarkMethod (ov); + MarkExplicitInterfaceImplementation (method, ov); + } + } + + MarkMethodSpecialCustomAttributes (method); + + if (method.IsVirtual) + _virtual_methods.Add (method); + + MarkNewCodeDependencies (method); + + MarkBaseMethods (method); + + MarkType (method.ReturnType); + MarkCustomAttributes (method.MethodReturnType); + MarkMarshalSpec (method.MethodReturnType); + + if (method.IsPInvokeImpl || method.IsInternalCall) { + ProcessInteropMethod (method); + } + + if (ShouldParseMethodBody (method)) + MarkMethodBody (method.Body); + + DoAdditionalMethodProcessing (method); + + Annotations.Mark (method); + + ApplyPreserveMethods (method); + Tracer.Pop (); + } + + // Allow subclassers to mark additional things when marking a method + protected virtual void DoAdditionalMethodProcessing (MethodDefinition method) + { + } + + protected virtual bool ShouldMarkAsInstancePossible (MethodDefinition method) + { + // We don't need to mark it multiple times + if (Annotations.IsInstantiated (method.DeclaringType)) + return false; + + if (method.IsInstanceConstructor ()) + return true; + + if (method.DeclaringType.IsInterface) + return true; + + return false; + } + + protected virtual void MarkRequirementsForInstantiatedTypes (TypeDefinition type) + { + if (Annotations.IsInstantiated (type)) + return; + + Annotations.MarkInstantiated (type); + + MarkInterfaceImplementations (type); + + foreach (var method in GetRequiredMethodsForInstantiatedType (type)) + MarkMethod (method); + + DoAdditionalInstantiatedTypeProcessing (type); + } + + /// + /// Collect methods that must be marked once a type is determined to be instantiated. + /// + /// This method is virtual in order to give derived mark steps an opportunity to modify the collection of methods that are needed + /// + /// + /// + protected virtual IEnumerable GetRequiredMethodsForInstantiatedType (TypeDefinition type) + { + foreach (var method in type.Methods) { + if (method.IsFinalizer () || IsVirtualNeededByInstantiatedTypeDueToPreservedScope (method)) + yield return method; + } + } + + void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReference ov) + { + var resolvedOverride = ov.Resolve (); + + if (resolvedOverride == null) { + HandleUnresolvedMethod (ov); + return; + } + + if (resolvedOverride.DeclaringType.IsInterface) { + foreach (var ifaceImpl in method.DeclaringType.Interfaces) { + var resolvedInterfaceType = ifaceImpl.InterfaceType.Resolve (); + if (resolvedInterfaceType == null) { + HandleUnresolvedType (ifaceImpl.InterfaceType); + continue; + } + + if (resolvedInterfaceType == resolvedOverride.DeclaringType) { + MarkInterfaceImplementation (ifaceImpl); + return; + } + } + } + } + + void MarkNewCodeDependencies (MethodDefinition method) + { + switch (Annotations.GetAction (method)) { + case MethodAction.ConvertToStub: + if (!method.IsInstanceConstructor ()) + return; + + var baseType = method.DeclaringType.BaseType.Resolve (); + if (!MarkDefaultConstructor (baseType)) + throw new NotSupportedException ($"Cannot stub constructor on '{method.DeclaringType}' when base type does not have default constructor"); + + break; + + case MethodAction.ConvertToThrow: + MarkAndCacheConvertToThrowExceptionCtor (); + break; + } + } + + protected virtual void MarkAndCacheConvertToThrowExceptionCtor () + { + if (_context.MarkedKnownMembers.NotSupportedExceptionCtorString != null) + return; + + var nse = BCL.FindPredefinedType ("System", "NotSupportedException", _context); + if (nse == null) + throw new NotSupportedException ("Missing predefined 'System.NotSupportedException' type"); + + MarkType (nse); + + var nseCtor = MarkMethodIf (nse.Methods, KnownMembers.IsNotSupportedExceptionCtorString); + if (nseCtor == null) + throw new MarkException ($"Could not find constructor on '{nse.FullName}'"); + + _context.MarkedKnownMembers.NotSupportedExceptionCtorString = nseCtor; + + var objectType = BCL.FindPredefinedType ("System", "Object", _context); + if (objectType == null) + throw new NotSupportedException ("Missing predefined 'System.Object' type"); + + MarkType (objectType); + + var objectCtor = MarkMethodIf (objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor); + if (objectCtor == null) + throw new MarkException ($"Could not find constructor on '{objectType.FullName}'"); + + _context.MarkedKnownMembers.ObjectCtor = objectCtor; + } + + bool MarkDisablePrivateReflectionAttribute () + { + if (_context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor != null) + return false; + + var nse = BCL.FindPredefinedType ("System.Runtime.CompilerServices", "DisablePrivateReflectionAttribute", _context); + if (nse == null) + throw new NotSupportedException ("Missing predefined 'System.Runtime.CompilerServices.DisablePrivateReflectionAttribute' type"); + + MarkType (nse); + + var ctor = MarkMethodIf (nse.Methods, MethodDefinitionExtensions.IsDefaultConstructor); + if (ctor == null) + throw new MarkException ($"Could not find constructor on '{nse.FullName}'"); + + _context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor; + return true; + } + + void MarkBaseMethods (MethodDefinition method) + { + var base_methods = Annotations.GetBaseMethods (method); + if (base_methods == null) + return; + + foreach (MethodDefinition base_method in base_methods) { + if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) + continue; + + MarkMethod (base_method); + MarkBaseMethods (base_method); + } + } + + void ProcessInteropMethod(MethodDefinition method) + { + TypeDefinition returnTypeDefinition = method.ReturnType.Resolve (); + + const bool includeStaticFields = false; + if (returnTypeDefinition != null && !returnTypeDefinition.IsImport) { + MarkDefaultConstructor (returnTypeDefinition); + MarkFields (returnTypeDefinition, includeStaticFields); + } + + if (method.HasThis && !method.DeclaringType.IsImport) { + MarkFields (method.DeclaringType, includeStaticFields); + } + + foreach (ParameterDefinition pd in method.Parameters) { + TypeReference paramTypeReference = pd.ParameterType; + if (paramTypeReference is TypeSpecification) { + paramTypeReference = (paramTypeReference as TypeSpecification).ElementType; + } + TypeDefinition paramTypeDefinition = paramTypeReference.Resolve (); + if (paramTypeDefinition != null && !paramTypeDefinition.IsImport) { + MarkFields (paramTypeDefinition, includeStaticFields); + if (pd.ParameterType.IsByReference) { + MarkDefaultConstructor (paramTypeDefinition); + } + } + } + } + + protected virtual bool ShouldParseMethodBody (MethodDefinition method) + { + if (!method.HasBody) + return false; + + switch (Annotations.GetAction (method)) { + case MethodAction.ForceParse: + return true; + case MethodAction.Parse: + AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope); + switch (Annotations.GetAction (assembly)) { + case AssemblyAction.Link: + case AssemblyAction.Copy: + case AssemblyAction.CopyUsed: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + return true; + default: + return false; + } + default: + return false; + } + } + + protected void MarkProperty (PropertyDefinition prop) + { + MarkCustomAttributes (prop); + DoAdditionalPropertyProcessing (prop); + } + + protected virtual void MarkEvent (EventDefinition evt) + { + MarkCustomAttributes (evt); + MarkMethodIfNotNull (evt.AddMethod); + MarkMethodIfNotNull (evt.InvokeMethod); + MarkMethodIfNotNull (evt.RemoveMethod); + DoAdditionalEventProcessing (evt); + } + + void MarkMethodIfNotNull (MethodReference method) + { + if (method == null) + return; + + MarkMethod (method); + } + + protected virtual void MarkMethodBody (MethodBody body) + { + if (_context.IsOptimizationEnabled (CodeOptimizations.UnreachableBodies) && IsUnreachableBody (body)) { + MarkAndCacheConvertToThrowExceptionCtor (); + _unreachableBodies.Add (body); + return; + } + + foreach (VariableDefinition var in body.Variables) + MarkType (var.VariableType); + + foreach (ExceptionHandler eh in body.ExceptionHandlers) + if (eh.HandlerType == ExceptionHandlerType.Catch) + MarkType (eh.CatchType); + + foreach (Instruction instruction in body.Instructions) + MarkInstruction (instruction); + + MarkInterfacesNeededByBodyStack (body); + + MarkReflectionLikeDependencies (body); + + PostMarkMethodBody (body); + } + + bool IsUnreachableBody (MethodBody body) + { + return !body.Method.IsStatic + && !Annotations.IsInstantiated (body.Method.DeclaringType) + && MethodBodyScanner.IsWorthConvertingToThrow (body); + } + + + partial void PostMarkMethodBody (MethodBody body); + + void MarkInterfacesNeededByBodyStack (MethodBody body) + { + // If a type could be on the stack in the body and an interface it implements could be on the stack on the body + // then we need to mark that interface implementation. When this occurs it is not safe to remove the interface implementation from the type + // even if the type is never instantiated + var implementations = MethodBodyScanner.GetReferencedInterfaces (_context.Annotations, body); + if (implementations == null) + return; + + foreach (var implementation in implementations) + MarkInterfaceImplementation (implementation); + } + + protected virtual void MarkInstruction (Instruction instruction) + { + switch (instruction.OpCode.OperandType) { + case OperandType.InlineField: + MarkField ((FieldReference) instruction.Operand); + break; + case OperandType.InlineMethod: + MarkMethod ((MethodReference) instruction.Operand); + break; + case OperandType.InlineTok: + object token = instruction.Operand; + if (token is TypeReference) + MarkType ((TypeReference) token); + else if (token is MethodReference) + MarkMethod ((MethodReference) token); + else + MarkField ((FieldReference) token); + break; + case OperandType.InlineType: + MarkType ((TypeReference) instruction.Operand); + break; + default: + break; + } + } + + protected virtual void HandleUnresolvedType (TypeReference reference) + { + if (!_context.IgnoreUnresolved) { + throw new ResolutionException (reference); + } + } + + protected virtual void HandleUnresolvedMethod (MethodReference reference) + { + if (!_context.IgnoreUnresolved) { + throw new ResolutionException (reference); + } + } + + protected virtual void HandleUnresolvedField (FieldReference reference) + { + if (!_context.IgnoreUnresolved) { + throw new ResolutionException (reference); + } + } + + protected virtual bool ShouldMarkInterfaceImplementation (TypeDefinition type, InterfaceImplementation iface, TypeDefinition resolvedInterfaceType) + { + if (Annotations.IsMarked (iface)) + return false; + + if (Annotations.IsMarked (resolvedInterfaceType)) + return true; + + if (!_context.IsOptimizationEnabled (CodeOptimizations.UnusedInterfaces)) + return true; + + // It's hard to know if a com or windows runtime interface will be needed from managed code alone, + // so as a precaution we will mark these interfaces once the type is instantiated + if (resolvedInterfaceType.IsImport || resolvedInterfaceType.IsWindowsRuntime) + return true; + + return IsFullyPreserved (type); + } + + protected virtual void MarkInterfaceImplementation (InterfaceImplementation iface) + { + MarkCustomAttributes (iface); + MarkType (iface.InterfaceType); + Annotations.Mark (iface); + } + + bool HasManuallyTrackedDependency (MethodBody methodBody) + { + return PreserveDependencyLookupStep.HasPreserveDependencyAttribute (methodBody.Method); + } + + // + // Extension point for reflection logic handling customization + // + protected virtual bool ProcessReflectionDependency (MethodBody body, Instruction instruction) + { + return false; + } + + // + // Tries to mark additional dependencies used in reflection like calls (e.g. typeof (MyClass).GetField ("fname")) + // + protected virtual void MarkReflectionLikeDependencies (MethodBody body) + { + if (HasManuallyTrackedDependency (body)) + return; + + var instructions = body.Instructions; + ReflectionPatternDetector detector = new ReflectionPatternDetector (this, body.Method); + + // + // Starting at 1 because all patterns require at least 1 instruction backward lookup + // + for (var i = 1; i < instructions.Count; i++) { + var instruction = instructions [i]; + + if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt) + continue; + + if (ProcessReflectionDependency (body, instruction)) + continue; + + if (!(instruction.Operand is MethodReference methodCalled)) + continue; + + var methodCalledDefinition = methodCalled.Resolve (); + if (methodCalledDefinition == null) + continue; + + ReflectionPatternContext reflectionContext = new ReflectionPatternContext (_context, body.Method, methodCalledDefinition, i); + try { + detector.Process (ref reflectionContext); + } + finally { + reflectionContext.Dispose (); + } + } + } + + /// + /// Helper struct to pass around context information about reflection pattern + /// as a single parameter (and have a way to extend this in the future if we need to easily). + /// Also implements a simple validation mechanism to check that the code does report patter recognition + /// results for all methods it works on. + /// The promise of the pattern recorder is that for a given reflection method, it will either not talk + /// about it ever, or it will always report recognized/unrecognized. + /// + struct ReflectionPatternContext : IDisposable + { + readonly LinkContext _context; +#if DEBUG + bool _patternAnalysisAttempted; + bool _patternReported; +#endif + + public MethodDefinition MethodCalling { get; private set; } + public MethodDefinition MethodCalled { get; private set; } + public int InstructionIndex { get; private set; } + + public ReflectionPatternContext (LinkContext context, MethodDefinition methodCalling, MethodDefinition methodCalled, int instructionIndex) + { + _context = context; + MethodCalling = methodCalling; + MethodCalled = methodCalled; + InstructionIndex = instructionIndex; + +#if DEBUG + _patternAnalysisAttempted = false; + _patternReported = false; +#endif + } + + [Conditional("DEBUG")] + public void AnalyzingPattern () + { +#if DEBUG + _patternAnalysisAttempted = true; +#endif + } + + public void RecordRecognizedPattern (T accessedItem, Action mark) + where T : IMemberDefinition + { +#if DEBUG + Debug.Assert (_patternAnalysisAttempted, "To correctly report all patterns, when starting to analyze a pattern the AnalyzingPattern must be called first."); + _patternReported = true; +#endif + + _context.Tracer.Push ($"Reflection-{accessedItem}"); + try { + mark (); + _context.ReflectionPatternRecorder.RecognizedReflectionAccessPattern (MethodCalling, MethodCalled, accessedItem); + } finally { + _context.Tracer.Pop (); + } + } + + public void RecordUnrecognizedPattern (string message) + { +#if DEBUG + Debug.Assert (_patternAnalysisAttempted, "To correctly report all patterns, when starting to analyze a pattern the AnalyzingPattern must be called first."); + _patternReported = true; +#endif + + _context.ReflectionPatternRecorder.UnrecognizedReflectionAccessPattern (MethodCalling, MethodCalled, message); + } + + public void Dispose () + { +#if DEBUG + Debug.Assert(!_patternAnalysisAttempted || _patternReported, "A reflection pattern was analyzed, but no result was reported."); +#endif + } + } + + class ReflectionPatternDetector + { + readonly MarkStep _markStep; + readonly MethodDefinition _methodCalling; + readonly Collection _instructions; + + public ReflectionPatternDetector (MarkStep markStep, MethodDefinition callingMethod) + { + _markStep = markStep; + _methodCalling = callingMethod; + _instructions = _methodCalling.Body.Instructions; + } + + public void Process (ref ReflectionPatternContext reflectionContext) + { + var methodCalled = reflectionContext.MethodCalled; + var instructionIndex = reflectionContext.InstructionIndex; + var methodCalledType = methodCalled.DeclaringType; + + switch (methodCalledType.Name) { + // + // System.Type + // + case "Type" when methodCalledType.Namespace == "System": + + // Some of the overloads are implemented by calling another overload of the same name. + // These "internal" calls are not interesting to analyze, the outermost call is the one + // which needs to be analyzed. The assumption is that all overloads have the same semantics. + // (for example that all overload of GetConstructor if used require the specified type to have a .ctor). + if (_methodCalling.DeclaringType == methodCalled.DeclaringType && _methodCalling.Name == methodCalled.Name) + break; + + switch (methodCalled.Name) { + // + // GetConstructor (Type []) + // GetConstructor (BindingFlags, Binder, Type [], ParameterModifier []) + // GetConstructor (BindingFlags, Binder, CallingConventions, Type [], ParameterModifier []) + // + case "GetConstructor": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Constructor, instructionIndex - 1); + + break; + + // + // GetMethod (string) + // GetMethod (string, BindingFlags) + // GetMethod (string, Type[]) + // GetMethod (string, Type[], ParameterModifier[]) + // GetMethod (string, BindingFlags, Binder, Type[], ParameterModifier[]) + // GetMethod (string, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[]) + // + // TODO: .NET Core extensions + // GetMethod (string, int, Type[]) + // GetMethod (string, int, Type[], ParameterModifier[]?) + // GetMethod (string, int, BindingFlags, Binder?, Type[], ParameterModifier[]?) + // GetMethod (string, int, BindingFlags, Binder?, CallingConventions, Type[], ParameterModifier[]?) + // + case "GetMethod": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1); + + break; + + // + // GetField (string) + // GetField (string, BindingFlags) + // + case "GetField": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1); + + break; + + // + // GetEvent (string) + // GetEvent (string, BindingFlags) + // + case "GetEvent": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1); + + break; + + // + // GetProperty (string) + // GetProperty (string, BindingFlags) + // GetProperty (string, Type) + // GetProperty (string, Type[]) + // GetProperty (string, Type, Type[]) + // GetProperty (string, Type, Type[], ParameterModifier[]) + // GetProperty (string, BindingFlags, Binder, Type, Type[], ParameterModifier[]) + // + case "GetProperty": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1); + + break; + + // + // GetType (string) + // GetType (string, Boolean) + // GetType (string, Boolean, Boolean) + // GetType (string, Func, Func) + // GetType (string, Func, Func, Boolean) + // GetType (string, Func, Func, Boolean, Boolean) + // + case "GetType": + if (!methodCalled.IsStatic) { + break; + } else { + reflectionContext.AnalyzingPattern (); + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + + // + // The next value must be string constant (we don't handle anything else) + // + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with argument which cannot be analyzed"); + break; + } + + string typeName = (string)first_arg.Operand; + TypeDefinition foundType = _markStep.ResolveFullyQualifiedTypeName (typeName); + if (foundType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with type name `{typeName}` which can't be resolved."); + break; + } + + reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkType (foundType)); + } + break; + } + + break; + + // + // System.Linq.Expressions.Expression + // + case "Expression" when methodCalledType.Namespace == "System.Linq.Expressions": + Instruction second_argument; + TypeDefinition declaringType; + + if (!methodCalled.IsStatic) + break; + + switch (methodCalled.Name) { + + // + // static Call (Type, String, Type[], Expression[]) + // + case "Call": { + reflectionContext.AnalyzingPattern (); + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 4); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldtoken) + first_arg_instr++; + + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); + break; + } + + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); + second_argument = _instructions [second_arg_instr]; + if (second_argument.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); + break; + } + + var name = (string)second_argument.Operand; + + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, null, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } + + break; + + // + // static Property(Expression, Type, String) + // static Field (Expression, Type, String) + // + case "Property": + case "Field": { + reflectionContext.AnalyzingPattern (); + + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 2); + if (second_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + + var second_arg = _instructions [second_arg_instr]; + if (second_arg.OpCode == OpCodes.Ldtoken) + second_arg_instr++; + + declaringType = FindReflectionTypeForLookup (_instructions, second_arg_instr); + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); + break; + } + + var third_arg_inst = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); + var third_argument = _instructions [third_arg_inst]; + if (third_argument.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with the 3rd argument which cannot be analyzed"); + break; + } + + var name = (string)third_argument.Operand; + + // + // The first argument can be any expression but we are looking only for simple null + // which we can convert to static only field lookup + // + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); + bool staticOnly = false; + + if (first_arg_instr >= 0) { + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldnull) + staticOnly = true; + } + + if (methodCalled.Name [0] == 'P') + MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); + else + MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); + } + + break; + + // + // static New (Type) + // + case "New": { + reflectionContext.AnalyzingPattern (); + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldtoken) + first_arg_instr++; + + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); + break; + } + + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, BindingFlags.Instance, parametersCount: 0); + } + break; + } + + break; + + // + // System.Reflection.RuntimeReflectionExtensions + // + case "RuntimeReflectionExtensions" when methodCalledType.Namespace == "System.Reflection": + switch (methodCalled.Name) { + // + // static GetRuntimeField (this Type type, string name) + // + case "GetRuntimeField": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1, thisExtension: true); + break; + + // + // static GetRuntimeMethod (this Type type, string name, Type[] parameters) + // + case "GetRuntimeMethod": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1, thisExtension: true); + break; + + // + // static GetRuntimeProperty (this Type type, string name) + // + case "GetRuntimeProperty": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1, thisExtension: true); + break; + + // + // static GetRuntimeEvent (this Type type, string name) + // + case "GetRuntimeEvent": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1, thisExtension: true); + break; + } + + break; + + // + // System.AppDomain + // + case "AppDomain" when methodCalledType.Namespace == "System": + // + // CreateInstance (string assemblyName, string typeName) + // CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstance (string assemblyName, string typeName, object? []? activationAttributes) + // + // CreateInstanceAndUnwrap (string assemblyName, string typeName) + // CreateInstanceAndUnwrap (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceAndUnwrap (string assemblyName, string typeName, object? []? activationAttributes) + // + // CreateInstanceFrom (string assemblyFile, string typeName) + // CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) + // + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName) + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, object? []? activationAttributes) + // + switch (methodCalled.Name) { + case "CreateInstance": + case "CreateInstanceAndUnwrap": + case "CreateInstanceFrom": + case "CreateInstanceFromAndUnwrap": + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); + break; + } + + break; + + // + // System.Reflection.Assembly + // + case "Assembly" when methodCalledType.Namespace == "System.Reflection": + // + // CreateInstance (string typeName) + // CreateInstance (string typeName, bool ignoreCase) + // CreateInstance (string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object []? args, CultureInfo? culture, object []? activationAttributes) + // + if (methodCalled.Name == "CreateInstance") { + // + // TODO: This could be supported for `this` only calls + // + reflectionContext.AnalyzingPattern (); + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not yet supported"); + break; + } + + break; + + // + // System.Activator + // + case "Activator" when methodCalledType.Namespace == "System": + if (!methodCalled.IsStatic) + break; + + switch (methodCalled.Name) { + // + // static T CreateInstance () + // + case "CreateInstance" when methodCalled.ContainsGenericParameter: + // Not sure it's worth implementing as we cannot expant T and simple cases can be rewritten + reflectionContext.AnalyzingPattern (); + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not supported"); + break; + + // + // static CreateInstance (string assemblyName, string typeName) + // static CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + // static CreateInstance (string assemblyName, string typeName, object?[]? activationAttributes) + // + // static CreateInstance (System.Type type) + // static CreateInstance (System.Type type, bool nonPublic) + // static CreateInstance (System.Type type, params object?[]? args) + // static CreateInstance (System.Type type, object?[]? args, object?[]? activationAttributes) + // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture) + // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } + // + case "CreateInstance": { + reflectionContext.AnalyzingPattern (); + + var parameters = methodCalled.Parameters; + if (parameters.Count < 1) + break; + + if (parameters [0].ParameterType.MetadataType == MetadataType.String) { + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, parameters.Count < 4); + break; + } + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + + if (parameters [0].ParameterType.IsTypeOf ("System", "Type")) { + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr + 1); + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument expression which cannot be analyzed"); + break; + } + + BindingFlags bindingFlags = BindingFlags.Instance; + int? parametersCount = null; + + if (methodCalled.Parameters.Count == 1) { + parametersCount = 0; + } else { + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count - 1); + second_argument = _instructions [second_arg_instr]; + switch (second_argument.OpCode.Code) { + case Code.Ldc_I4_0 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: + parametersCount = 0; + bindingFlags |= BindingFlags.Public; + break; + case Code.Ldc_I4_1 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: + parametersCount = 0; + break; + case Code.Ldc_I4_S when parameters [1].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags"): + bindingFlags = (BindingFlags)(sbyte)second_argument.Operand; + break; + } + } + + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags, parametersCount); + break; + } + } + + break; + + // + // static CreateInstanceFrom (string assemblyFile, string typeName) + // static CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // static CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) + // + case "CreateInstanceFrom": + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); + break; + } + + break; + } + + } + + // + // Handles static method calls in form of Create (string assemblyFile, string typeName, ......) + // + void ProcessActivatorCallWithStrings (ref ReflectionPatternContext reflectionContext, int startIndex, bool defaultCtorOnly) + { + reflectionContext.AnalyzingPattern (); + + var parameters = reflectionContext.MethodCalled.Parameters; + if (parameters.Count < 2) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' is not supported"); + return; + } + + if (parameters [0].ParameterType.MetadataType != MetadataType.String && parameters [1].ParameterType.MetadataType != MetadataType.String) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' is not supported"); + return; + } + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, startIndex, reflectionContext.MethodCalled.Parameters.Count); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + return; + } + + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with the 1st argument which cannot be analyzed"); + return; + } + + var second_arg_instr = GetInstructionAtStackDepth (_instructions, startIndex, reflectionContext.MethodCalled.Parameters.Count - 1); + if (second_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + return; + } + + var second_arg = _instructions [second_arg_instr]; + if (second_arg.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with the 2nd argument which cannot be analyzed"); + return; + } + + string assembly_name = (string)first_arg.Operand; + if (!_markStep._context.Resolver.AssemblyCache.TryGetValue (assembly_name, out var assembly)) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' references assembly '{assembly_name}' which could not be found"); + return; + } + + string type_name = (string)second_arg.Operand; + var declaringType = FindType (assembly, type_name); + + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' references type '{type_name}' which could not be found"); + return; + } + + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, null, defaultCtorOnly ? 0 : (int?)null); + } + + // + // Handles instance methods called over typeof (Foo) with string name as the first argument + // + void ProcessSystemTypeGetMemberLikeCall (ref ReflectionPatternContext reflectionContext, System.Reflection.MemberTypes memberTypes, int startIndex, bool thisExtension = false) + { + reflectionContext.AnalyzingPattern (); + + int first_instance_arg = reflectionContext.MethodCalled.Parameters.Count; + if (thisExtension) + --first_instance_arg; + + var first_arg_instr = GetInstructionAtStackDepth (_instructions, startIndex, first_instance_arg); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + return; + } + + var first_arg = _instructions [first_arg_instr]; + BindingFlags? bindingFlags = default; + string name = default; + + if (memberTypes == System.Reflection.MemberTypes.Constructor) { + if (first_arg.OpCode == OpCodes.Ldc_I4_S && reflectionContext.MethodCalled.Parameters.Count > 0 && reflectionContext.MethodCalled.Parameters [0].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags")) { + bindingFlags = (BindingFlags)(sbyte)first_arg.Operand; + } + } else { + // + // The next value must be string constant (we don't handle anything else) + // + if (first_arg.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with argument which cannot be analyzed"); + return; + } + + name = (string)first_arg.Operand; + + var pos_arg = _instructions [first_arg_instr + 1]; + if (pos_arg.OpCode == OpCodes.Ldc_I4_S && reflectionContext.MethodCalled.Parameters.Count > 1 && reflectionContext.MethodCalled.Parameters [1].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags")) { + bindingFlags = (BindingFlags)(sbyte)pos_arg.Operand; + } + } + + var declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr - 1); + if (declaringType == null) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' does not use detectable instance type extraction"); + return; + } + + switch (memberTypes) { + case System.Reflection.MemberTypes.Constructor: + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags); + break; + case System.Reflection.MemberTypes.Method: + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, 0, bindingFlags); + break; + case System.Reflection.MemberTypes.Field: + MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name); + break; + case System.Reflection.MemberTypes.Property: + MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name); + break; + case System.Reflection.MemberTypes.Event: + MarkEventsFromReflectionCall (ref reflectionContext, declaringType, name); + break; + default: + Debug.Fail ("Unsupported member type"); + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' is of unexpected member type."); + break; + } + } + + // + // arity == null for name match regardless of arity + // + void MarkMethodsFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, int? arity, BindingFlags? bindingFlags, int? parametersCount = null) + { + bool foundMatch = false; + foreach (var method in declaringType.Methods) { + var mname = method.Name; + + // Either exact match or generic method with any arity when unspecified + if (mname != name && !(arity == null && mname.StartsWith (name, StringComparison.Ordinal) && mname.Length > name.Length + 2 && mname [name.Length + 1] == '`')) { + continue; + } + + if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Static && !method.IsStatic) + continue; + + if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Instance && method.IsStatic) + continue; + + if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public && !method.IsPublic) + continue; + + if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic && method.IsPublic) + continue; + + if (parametersCount != null && parametersCount != method.Parameters.Count) + continue; + + foundMatch = true; + reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method)); + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve method `{name}` on type `{declaringType.FullName}`."); + } + + void MarkPropertiesFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, bool staticOnly = false) + { + bool foundMatch = false; + foreach (var property in declaringType.Properties) { + if (property.Name != name) + continue; + + bool markedAny = false; + + // It is not easy to reliably detect in the IL code whether the getter or setter (or both) are used. + // Be conservative and mark everything for the property. + var getter = property.GetMethod; + if (getter != null && (!staticOnly || staticOnly && getter.IsStatic)) { + reflectionContext.RecordRecognizedPattern (getter, () => _markStep.MarkIndirectlyCalledMethod (getter)); + markedAny = true; + } + + var setter = property.SetMethod; + if (setter != null && (!staticOnly || staticOnly && setter.IsStatic)) { + reflectionContext.RecordRecognizedPattern (setter, () => _markStep.MarkIndirectlyCalledMethod (setter)); + markedAny = true; + } + + if (markedAny) { + foundMatch = true; + reflectionContext.RecordRecognizedPattern (property, () => _markStep.MarkProperty (property)); + } + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve property `{name}` on type `{declaringType.FullName}`."); + } + + void MarkFieldsFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, bool staticOnly = false) + { + bool foundMatch = false; + foreach (var field in declaringType.Fields) { + if (field.Name != name) + continue; + + if (staticOnly && !field.IsStatic) + continue; + + foundMatch = true; + reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field)); + break; + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve field `{name}` on type `{declaringType.FullName}`."); + } + + void MarkEventsFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name) + { + bool foundMatch = false; + foreach (var eventInfo in declaringType.Events) { + if (eventInfo.Name != name) + continue; + + foundMatch = true; + reflectionContext.RecordRecognizedPattern (eventInfo, () => _markStep.MarkEvent (eventInfo)); + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve event `{name}` on type `{declaringType.FullName}`."); + } + } + + static int GetInstructionAtStackDepth (Collection instructions, int startIndex, int stackSizeToBacktrace) + { + for (int i = startIndex; i >= 0; --i) { + var instruction = instructions [i]; + + switch (instruction.OpCode.StackBehaviourPop) { + case StackBehaviour.Pop0: + break; + case StackBehaviour.Pop1: + case StackBehaviour.Popi: + case StackBehaviour.Popref: + stackSizeToBacktrace++; + break; + case StackBehaviour.Pop1_pop1: + case StackBehaviour.Popi_pop1: + case StackBehaviour.Popi_popi: + case StackBehaviour.Popi_popi8: + case StackBehaviour.Popi_popr4: + case StackBehaviour.Popi_popr8: + case StackBehaviour.Popref_pop1: + case StackBehaviour.Popref_popi: + stackSizeToBacktrace += 2; + break; + case StackBehaviour.Popref_popi_popi: + case StackBehaviour.Popref_popi_popi8: + case StackBehaviour.Popref_popi_popr4: + case StackBehaviour.Popref_popi_popr8: + case StackBehaviour.Popref_popi_popref: + stackSizeToBacktrace += 3; + break; + case StackBehaviour.Varpop: + switch (instruction.OpCode.Code) { + case Code.Call: + case Code.Calli: + case Code.Callvirt: + if (instruction.Operand is MethodReference mr) { + stackSizeToBacktrace += mr.Parameters.Count; + if (mr.Resolve ()?.IsStatic == false) + stackSizeToBacktrace++; + } + + break; + case Code.Newobj: + if (instruction.Operand is MethodReference ctor) { + stackSizeToBacktrace += ctor.Parameters.Count; + } + break; + case Code.Ret: + // TODO: Need method return type for correct stack size but this path should not be hit yet + break; + default: + return -3; + } + break; + } + + switch (instruction.OpCode.StackBehaviourPush) { + case StackBehaviour.Push0: + break; + case StackBehaviour.Push1: + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + case StackBehaviour.Pushref: + stackSizeToBacktrace--; + break; + case StackBehaviour.Push1_push1: + stackSizeToBacktrace -= 2; + break; + case StackBehaviour.Varpush: + // + // Only call, calli, callvirt will hit this + // + if (instruction.Operand is MethodReference mr && mr.ReturnType.MetadataType != MetadataType.Void) { + stackSizeToBacktrace--; + } + break; + } + + if (stackSizeToBacktrace == 0) + return i; + + if (stackSizeToBacktrace < 0) + return -1; + } + + return -2; + } + + static TypeDefinition FindReflectionTypeForLookup (Collection instructions, int startIndex) + { + while (startIndex >= 1) { + int storeIndex = -1; + var instruction = instructions [startIndex]; + switch (instruction.OpCode.Code) { + // + // Pattern #1 + // + // typeof (Foo).ReflectionCall () + // + case Code.Call: + if (!(instruction.Operand is MethodReference mr) || mr.Name != "GetTypeFromHandle") + return null; + + var ldtoken = instructions [startIndex - 1]; + + if (ldtoken.OpCode != OpCodes.Ldtoken) + return null; + + return (ldtoken.Operand as TypeReference).Resolve (); + + // + // Patern #2 + // + // var temp = typeof (Foo); + // temp.ReflectionCall () + // + case Code.Ldloc_0: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_0, startIndex - 1); + startIndex = storeIndex - 1; + break; + case Code.Ldloc_1: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_1, startIndex - 1); + startIndex = storeIndex - 1; + break; + case Code.Ldloc_2: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_2, startIndex - 1); + startIndex = storeIndex - 1; + break; + case Code.Ldloc_3: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_3, startIndex - 1); + startIndex = storeIndex - 1; + break; + case Code.Ldloc_S: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_S, startIndex - 1, l => (VariableReference)l.Operand == (VariableReference)instruction.Operand); + startIndex = storeIndex - 1; + break; + case Code.Ldloc: + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc, startIndex - 1, l => (VariableReference)l.Operand == (VariableReference)instruction.Operand); + startIndex = storeIndex - 1; + break; + + case Code.Nop: + startIndex--; + break; + + default: + return null; + } + } + + return null; + } + + static int GetIndexOfInstruction (Collection instructions, OpCode opcode, int startIndex, Predicate comparer = null) + { + while (startIndex >= 0) { + var instr = instructions [startIndex]; + if (instr.OpCode == opcode && (comparer == null || comparer (instr))) + return startIndex; + + startIndex--; + } + + return -1; + } + + protected class AttributeProviderPair { + public AttributeProviderPair (CustomAttribute attribute, ICustomAttributeProvider provider) + { + Attribute = attribute; + Provider = provider; + } + + public CustomAttribute Attribute { get; private set; } + public ICustomAttributeProvider Provider { get; private set; } + } + } + + // Make our own copy of the BindingFlags enum, so that we don't depend on System.Reflection. + [Flags] + enum BindingFlags + { + Default = 0, + IgnoreCase = 1, + DeclaredOnly = 2, + Instance = 4, + Static = 8, + Public = 16, + NonPublic = 32, + FlattenHierarchy = 64, + InvokeMethod = 256, + CreateInstance = 512, + GetField = 1024, + SetField = 2048, + GetProperty = 4096, + SetProperty = 8192, + PutDispProperty = 16384, + PutRefDispProperty = 32768, + ExactBinding = 65536, + SuppressChangeType = 131072, + OptionalParamBinding = 262144, + IgnoreReturn = 16777216 + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs new file mode 100644 index 000000000000..884f6a9a65f0 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs @@ -0,0 +1,299 @@ +// +// OutputStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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.Collections.Generic; +using System.IO; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.PE; + +namespace Mono.Linker.Steps { + + public class OutputStep : BaseStep { + private static Dictionary architectureMap; + + private enum NativeOSOverride { + Apple = 0x4644, + FreeBSD = 0xadc4, + Linux = 0x7b79, + NetBSD = 0x1993, + Default = 0 + } + + List assembliesWritten; + + public OutputStep () { + assembliesWritten = new List (); + } + + static TargetArchitecture CalculateArchitecture (TargetArchitecture readyToRunArch) + { + if (architectureMap == null) { + architectureMap = new Dictionary (); + foreach (var os in Enum.GetValues (typeof (NativeOSOverride))) { + ushort osVal = (ushort) (NativeOSOverride) os; + foreach (var arch in Enum.GetValues (typeof (TargetArchitecture))) { + ushort archVal = (ushort) (TargetArchitecture)arch; + architectureMap.Add ((ushort) (archVal ^ osVal), (TargetArchitecture) arch); + } + } + } + + TargetArchitecture pureILArch; + if (architectureMap.TryGetValue ((ushort) readyToRunArch, out pureILArch)) { + return pureILArch; + } + throw new BadImageFormatException ("unrecognized module attributes"); + } + + protected override void Process () + { + CheckOutputDirectory (); + Tracer.Finish (); + } + + protected override void EndProcess () + { + if (Context.AssemblyListFile != null) { + using (var w = File.CreateText (Context.AssemblyListFile)) { + w.WriteLine ("[" + String.Join (", ", assembliesWritten.Select (a => "\"" + a + "\"").ToArray ()) + "]"); + } + } + } + + void CheckOutputDirectory () + { + if (Directory.Exists (Context.OutputDirectory)) + return; + + Directory.CreateDirectory (Context.OutputDirectory); + } + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + OutputAssembly (assembly); + } + + protected void WriteAssembly (AssemblyDefinition assembly, string directory) + { + WriteAssembly (assembly, directory, SaveSymbols (assembly)); + } + + protected virtual void WriteAssembly (AssemblyDefinition assembly, string directory, WriterParameters writerParameters) + { + foreach (var module in assembly.Modules) { + // Write back pure IL even for crossgen-ed assemblies + if (module.IsCrossgened ()) { + module.Attributes |= ModuleAttributes.ILOnly; + module.Attributes ^= ModuleAttributes.ILLibrary; + module.Architecture = CalculateArchitecture (module.Architecture); + } + } + + string outputName = GetAssemblyFileName (assembly, directory); + try { + assembly.Write (outputName, writerParameters); + } catch (Exception e) { + throw new OutputException ($"Failed to write '{outputName}", e); + } + } + + void OutputAssembly (AssemblyDefinition assembly) + { + string directory = Context.OutputDirectory; + + CopyConfigFileIfNeeded (assembly, directory); + + var action = Annotations.GetAction (assembly); + Context.LogMessage (MessageImportance.Low, $"Output action: {action,8} assembly: {assembly}"); + + switch (action) { + case AssemblyAction.Save: + case AssemblyAction.Link: + case AssemblyAction.AddBypassNGen: + Context.Tracer.AddDependency (assembly); + WriteAssembly (assembly, directory); + CopySatelliteAssembliesIfNeeded (assembly, directory); + assembliesWritten.Add (GetOriginalAssemblyFileInfo (assembly).Name); + break; + case AssemblyAction.Copy: + Context.Tracer.AddDependency (assembly); + CloseSymbols (assembly); + CopyAssembly (assembly, directory); + CopySatelliteAssembliesIfNeeded (assembly, directory); + assembliesWritten.Add (GetOriginalAssemblyFileInfo (assembly).Name); + break; + case AssemblyAction.Delete: + CloseSymbols (assembly); + DeleteAssembly (assembly, directory); + break; + default: + CloseSymbols (assembly); + break; + } + } + + protected virtual void DeleteAssembly(AssemblyDefinition assembly, string directory) + { + var target = GetAssemblyFileName (assembly, directory); + if (File.Exists (target)) { + File.Delete (target); + File.Delete (target + ".mdb"); + File.Delete (Path.ChangeExtension (target, "pdb")); + File.Delete (GetConfigFile (target)); + } + } + + void CloseSymbols (AssemblyDefinition assembly) + { + Annotations.CloseSymbolReader (assembly); + } + + WriterParameters SaveSymbols (AssemblyDefinition assembly) + { + var parameters = new WriterParameters { + DeterministicMvid = Context.DeterministicOutput + }; + + if (!Context.LinkSymbols) + return parameters; + + if (!assembly.MainModule.HasSymbols) + return parameters; + + // Use a string check to avoid a hard dependency on Mono.Cecil.Pdb + if (Environment.OSVersion.Platform != PlatformID.Win32NT && assembly.MainModule.SymbolReader.GetType ().FullName == "Mono.Cecil.Pdb.NativePdbReader") + return parameters; + + if (Context.SymbolWriterProvider != null) + parameters.SymbolWriterProvider = Context.SymbolWriterProvider; + else + parameters.WriteSymbols = true; + return parameters; + } + + + void CopySatelliteAssembliesIfNeeded (AssemblyDefinition assembly, string directory) + { + if (!Annotations.ProcessSatelliteAssemblies) + return; + + FileInfo original = GetOriginalAssemblyFileInfo (assembly); + string resourceFile = GetAssemblyResourceFileName (original.FullName); + + foreach (var subDirectory in Directory.EnumerateDirectories (original.DirectoryName)) { + var satelliteAssembly = Path.Combine (subDirectory, resourceFile); + if (!File.Exists (satelliteAssembly)) + continue; + + string cultureName = subDirectory.Substring (subDirectory.LastIndexOf (Path.DirectorySeparatorChar) + 1); + string culturePath = Path.Combine (directory, cultureName); + + Directory.CreateDirectory (culturePath); + File.Copy (satelliteAssembly, Path.Combine (culturePath, resourceFile), true); + } + } + + void CopyConfigFileIfNeeded (AssemblyDefinition assembly, string directory) + { + string config = GetConfigFile (GetOriginalAssemblyFileInfo (assembly).FullName); + if (!File.Exists (config)) + return; + + string target = Path.GetFullPath (GetConfigFile (GetAssemblyFileName (assembly, directory))); + + if (config == target) + return; + + File.Copy (config, GetConfigFile (GetAssemblyFileName (assembly, directory)), true); + } + + static string GetAssemblyResourceFileName (string assembly) + { + return Path.GetFileNameWithoutExtension (assembly) + ".resources.dll"; + } + + static string GetConfigFile (string assembly) + { + return assembly + ".config"; + } + + static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly) + { + return new FileInfo (assembly.MainModule.FileName); + } + + protected virtual void CopyAssembly (AssemblyDefinition assembly, string directory) + { + // Special case. When an assembly has embedded pdbs, link symbols is not enabled, and the assembly's action is copy, + // we want to match the behavior of assemblies with the other symbol types and end up with an assembly that does not have symbols. + // In order to do that, we can't simply copy files. We need to write the assembly without symbols + if (assembly.MainModule.HasSymbols && !Context.LinkSymbols && assembly.MainModule.SymbolReader is EmbeddedPortablePdbReader) { + WriteAssembly (assembly, directory, new WriterParameters ()); + return; + } + + FileInfo fi = GetOriginalAssemblyFileInfo (assembly); + string target = Path.GetFullPath (Path.Combine (directory, fi.Name)); + string source = fi.FullName; + if (source == target) + return; + + CopyFileAndRemoveReadOnly (source, target); + + if (!Context.LinkSymbols) + return; + + var mdb = source + ".mdb"; + if (File.Exists (mdb)) + CopyFileAndRemoveReadOnly (mdb, target + ".mdb"); + + var pdb = Path.ChangeExtension (source, "pdb"); + if (File.Exists (pdb)) + CopyFileAndRemoveReadOnly (pdb, Path.ChangeExtension (target, "pdb")); + } + + static void CopyFileAndRemoveReadOnly (string src, string dest) { + File.Copy (src, dest, true); + + System.IO.FileAttributes attrs = File.GetAttributes (dest); + + if ((attrs & System.IO.FileAttributes.ReadOnly) == System.IO.FileAttributes.ReadOnly) + File.SetAttributes (dest, attrs & ~System.IO.FileAttributes.ReadOnly); + } + + protected virtual string GetAssemblyFileName (AssemblyDefinition assembly, string directory) + { + string file = GetOriginalAssemblyFileInfo (assembly).Name; + return Path.Combine (directory, file); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs new file mode 100644 index 000000000000..437c67d73005 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs @@ -0,0 +1,99 @@ +// +// PreserveDependencyLookupStep.cs +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2018 Microsoft Corporation +// +// 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 Mono.Cecil; +using Mono.Collections.Generic; + +namespace Mono.Linker.Steps { + public class PreserveDependencyLookupStep : LoadReferencesStep { + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + var module = assembly.MainModule; + + foreach (var type in module.Types) { + if (type.HasMethods) { + foreach (var method in type.GetMethods ()) { + var md = method.Resolve (); + if (md?.HasCustomAttributes != true) + continue; + + ProcessPreserveDependencyAttribute (md.CustomAttributes); + } + } + + if (type.HasFields) { + foreach (var field in type.Fields) { + var md = field.Resolve (); + if (md?.HasCustomAttributes != true) + continue; + + ProcessPreserveDependencyAttribute (md.CustomAttributes); + } + } + } + } + + public static bool IsPreserveDependencyAttribute (TypeReference tr) + { + return tr.Name == "PreserveDependencyAttribute" && tr.Namespace == "System.Runtime.CompilerServices"; + } + + public static bool HasPreserveDependencyAttribute (MethodDefinition method) + { + if (!method.HasCustomAttributes) + return false; + + foreach (var ca in method.CustomAttributes) { + if (IsPreserveDependencyAttribute (ca.AttributeType)) + return true; + } + + return false; + } + + void ProcessPreserveDependencyAttribute (Collection attributes) + { + foreach (var ca in attributes) { + if (!IsPreserveDependencyAttribute (ca.AttributeType)) + continue; + + if (ca.ConstructorArguments.Count != 3) + continue; + + var assemblyName = ca.ConstructorArguments [2].Value as string; + if (assemblyName == null) + continue; + + var newDependency = Context.Resolve (new AssemblyNameReference (assemblyName, new Version ())); + if (newDependency != null) + ProcessReferences (newDependency); + } + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/RegenerateGuidStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/RegenerateGuidStep.cs new file mode 100644 index 000000000000..6b2558e8352d --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/RegenerateGuidStep.cs @@ -0,0 +1,48 @@ +// +// CleanStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2008 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; + +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class RegenerateGuidStep : BaseStep { + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + if (Annotations.GetAction (assembly) == AssemblyAction.Link) + RegenerateGuid (assembly); + } + + static void RegenerateGuid (AssemblyDefinition asm) + { + asm.MainModule.Mvid = Guid.NewGuid (); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs new file mode 100644 index 000000000000..f8a350a08e07 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs @@ -0,0 +1,252 @@ +// +// ResolveFromAssemblyStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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 Mono.Cecil; +using Mono.Collections.Generic; + +namespace Mono.Linker.Steps +{ + + public class ResolveFromAssemblyStep : ResolveStep + { + + AssemblyDefinition _assembly; + string _file; + RootVisibility _rootVisibility; + + public enum RootVisibility + { + Any = 0, + PublicAndFamily = 1, + PublicAndFamilyAndAssembly = 2 + } + + + public ResolveFromAssemblyStep (string assembly, RootVisibility rootVisibility = RootVisibility.Any) + { + _file = assembly; + _rootVisibility = rootVisibility; + } + + public ResolveFromAssemblyStep (AssemblyDefinition assembly) + { + _assembly = assembly; + } + + protected override void Process () + { + if (_assembly != null) + Context.Resolver.CacheAssembly (_assembly); + + var ignoreUnresolved = Context.Resolver.IgnoreUnresolved; + if (_rootVisibility == RootVisibility.PublicAndFamily) { + Context.Resolver.IgnoreUnresolved = false; + } + + AssemblyDefinition assembly = _assembly ?? Context.Resolve (_file); + Context.Resolver.IgnoreUnresolved = ignoreUnresolved; + if (_rootVisibility != RootVisibility.Any && HasInternalsVisibleTo (assembly)) { + _rootVisibility = RootVisibility.PublicAndFamilyAndAssembly; + } + + switch (assembly.MainModule.Kind) { + case ModuleKind.Dll: + ProcessLibrary (assembly); + break; + default: + ProcessExecutable (assembly); + break; + } + } + + protected virtual void ProcessLibrary (AssemblyDefinition assembly) + { + ProcessLibrary (Context, assembly, _rootVisibility); + } + + public static void ProcessLibrary (LinkContext context, AssemblyDefinition assembly, RootVisibility rootVisibility = RootVisibility.Any) + { + var action = rootVisibility == RootVisibility.Any ? AssemblyAction.Copy : AssemblyAction.Link; + context.SetAction (assembly, action); + + context.Tracer.Push (assembly); + + foreach (TypeDefinition type in assembly.MainModule.Types) + MarkType (context, type, rootVisibility); + + if (assembly.MainModule.HasExportedTypes) { + foreach (var exported in assembly.MainModule.ExportedTypes) { + bool isForwarder = exported.IsForwarder; + var declaringType = exported.DeclaringType; + while (!isForwarder && (declaringType != null)) { + isForwarder = declaringType.IsForwarder; + declaringType = declaringType.DeclaringType; + } + + if (!isForwarder) + continue; + TypeDefinition resolvedExportedType = exported.Resolve (); + + if (resolvedExportedType == null) { + // + // It's quite common for assemblies to have broken exported types + // + // One source of them is from native csc which added all nested types of + // type-forwarded types automatically including private ones. + // + // Next source of broken type-forwarders is from custom metadata writers which + // simply write bogus information. + // + // Both cases are bugs not on our end but we still want to link all assemblies + // especially when such types cannot be used anyway + // + context.LogMessage ($"Cannot find declaration of exported type '{exported}' from the assembly '{assembly}'"); + + continue; + } + + context.Resolve (resolvedExportedType.Scope); + MarkType (context, resolvedExportedType, rootVisibility); + context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule); + } + } + + context.Tracer.Pop (); + } + + static void MarkType (LinkContext context, TypeDefinition type, RootVisibility rootVisibility) + { + bool markType; + switch (rootVisibility) { + default: + markType = true; + break; + + case RootVisibility.PublicAndFamilyAndAssembly: + markType = !type.IsNestedPrivate; + break; + + case RootVisibility.PublicAndFamily: + markType = type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly; + break; + } + + if (!markType) { + return; + } + + context.Annotations.MarkAndPush (type); + + if (type.HasFields) + MarkFields (context, type.Fields, rootVisibility); + if (type.HasMethods) + MarkMethods (context, type.Methods, rootVisibility); + if (type.HasNestedTypes) + foreach (var nested in type.NestedTypes) + MarkType (context, nested, rootVisibility); + + context.Tracer.Pop (); + } + + void ProcessExecutable (AssemblyDefinition assembly) + { + Context.SetAction (assembly, AssemblyAction.Link); + + Tracer.Push (assembly); + + Annotations.Mark (assembly.EntryPoint.DeclaringType); + + MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse, RootVisibility.Any); + + Tracer.Pop (); + } + + static void MarkFields (LinkContext context, Collection fields, RootVisibility rootVisibility) + { + foreach (FieldDefinition field in fields) { + bool markField; + switch (rootVisibility) { + default: + markField = true; + break; + + case RootVisibility.PublicAndFamily: + markField = field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly; + break; + + case RootVisibility.PublicAndFamilyAndAssembly: + markField = field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly || field.IsAssembly || field.IsFamilyAndAssembly; + break; + } + if (markField) { + context.Annotations.Mark (field); + } + } + } + + static void MarkMethods (LinkContext context, Collection methods, RootVisibility rootVisibility) + { + foreach (MethodDefinition method in methods) + MarkMethod (context, method, MethodAction.ForceParse, rootVisibility); + } + + static void MarkMethod (LinkContext context, MethodDefinition method, MethodAction action, RootVisibility rootVisibility) + { + bool markMethod; + switch (rootVisibility) { + default: + markMethod = true; + break; + + case RootVisibility.PublicAndFamily: + markMethod = method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly; + break; + + case RootVisibility.PublicAndFamilyAndAssembly: + markMethod = method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly || method.IsAssembly || method.IsFamilyAndAssembly; + break; + } + + if (markMethod) { + context.Annotations.Mark (method); + context.Annotations.SetAction (method, action); + } + } + + static bool HasInternalsVisibleTo (AssemblyDefinition assembly) + { + foreach (CustomAttribute attribute in assembly.CustomAttributes) { + if (attribute.Constructor.DeclaringType.FullName == + "System.Runtime.CompilerServices.InternalsVisibleToAttribute") + return true; + } + + return false; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs new file mode 100644 index 000000000000..57e277400870 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs @@ -0,0 +1,140 @@ +// +// ResolveFromXApiStep.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Xml.XPath; + +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + + public class ResolveFromXApiStep : ResolveStep, IXApiVisitor + { + + static readonly string _name = "name"; + static readonly string _ns = string.Empty; + + XPathDocument _document; + + public ResolveFromXApiStep (XPathDocument document) + { + _document = document; + } + + protected override void Process () + { + XApiReader reader = new XApiReader (_document, this); + reader.Process (Context); + } + + public void OnAssembly (XPathNavigator nav, AssemblyDefinition assembly) + { + } + + public void OnAttribute (XPathNavigator nav) + { + string name = GetName (nav); + + TypeDefinition type = Context.GetType (name); + if (type != null) + MarkType (type); + } + + public void OnClass (XPathNavigator nav, TypeDefinition type) + { + MarkType (type); + } + + public void OnInterface (XPathNavigator nav, TypeDefinition type) + { + MarkType (type); + } + + public void OnField (XPathNavigator nav, FieldDefinition field) + { + MarkField (field); + } + + public void OnMethod (XPathNavigator nav, MethodDefinition method) + { + MarkMethod (method); + } + + public void OnConstructor (XPathNavigator nav, MethodDefinition method) + { + MarkMethod (method); + } + + public void OnProperty (XPathNavigator nav, PropertyDefinition property) + { + } + + public void OnEvent (XPathNavigator nav, EventDefinition evt) + { + if (evt.AddMethod != null) + MarkMethod (evt.AddMethod); + if (evt.InvokeMethod != null) + MarkMethod (evt.InvokeMethod); + if (evt.RemoveMethod != null) + MarkMethod (evt.RemoveMethod); + } + + static string GetName (XPathNavigator nav) + { + return GetAttribute (nav, _name); + } + + static string GetAttribute (XPathNavigator nav, string attribute) + { + return nav.GetAttribute (attribute, _ns); + } + + void MarkType (TypeDefinition type) + { + InternalMark (type); + } + + void MarkField (FieldDefinition field) + { + InternalMark (field); + } + + void InternalMark (IMetadataTokenProvider provider) + { + Annotations.Mark (provider); + Annotations.SetPublic (provider); + } + + void MarkMethod (MethodDefinition method) + { + InternalMark (method); + Annotations.MarkIndirectlyCalledMethod (method); + Annotations.SetAction (method, MethodAction.Parse); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs new file mode 100644 index 000000000000..bb4febed88ba --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs @@ -0,0 +1,727 @@ +// +// ResolveFromXmlStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// (C) 2007 Novell, Inc. +// Copyright 2013 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.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.XPath; + +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class XmlResolutionException : Exception { + public XmlResolutionException (string message, Exception innerException) + : base (message, innerException) + { + } + } + + public class ResolveFromXmlStep : ResolveStep { + + static readonly string _signature = "signature"; + static readonly string _fullname = "fullname"; + static readonly string _required = "required"; + static readonly string _preserve = "preserve"; + static readonly string _accessors = "accessors"; + static readonly string _ns = string.Empty; + + static readonly string[] _accessorsAll = new string[] { "all" }; + static readonly char[] _accessorsSep = new char[] { ';' }; + + XPathDocument _document; + string _xmlDocumentLocation; + string _resourceName; + AssemblyDefinition _resourceAssembly; + + public ResolveFromXmlStep (XPathDocument document, string xmlDocumentLocation = "") + { + _document = document; + _xmlDocumentLocation = xmlDocumentLocation; + } + + public ResolveFromXmlStep (XPathDocument document, string resourceName, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") + : this (document, xmlDocumentLocation) + { + if (string.IsNullOrEmpty (resourceName)) + throw new ArgumentNullException (nameof (resourceName)); + + if (resourceAssembly == null) + throw new ArgumentNullException (nameof (resourceAssembly)); + + _resourceName = resourceName; + _resourceAssembly = resourceAssembly; + } + + protected override void Process () + { + XPathNavigator nav = _document.CreateNavigator (); + + // This step can be created with XML files that aren't necessarily + // linker descriptor files. So bail if we don't have a element. + if (!nav.MoveToChild("linker", _ns)) + return; + + try { + ProcessAssemblies (Context, nav.SelectChildren ("assembly", _ns)); + + if (!string.IsNullOrEmpty (_resourceName) && Context.StripResources) + Context.Annotations.AddResourceToRemove (_resourceAssembly, _resourceName); + } catch (Exception ex) when (!(ex is XmlResolutionException)) { + throw new XmlResolutionException (string.Format ("Failed to process XML description: {0}", _xmlDocumentLocation), ex); + } + } + + protected virtual void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) { + AssemblyDefinition assembly = GetAssembly (context, GetAssemblyName (iterator.Current)); + if (assembly != null) + ProcessAssembly (assembly, iterator); + } + } + + protected virtual void ProcessAssembly (AssemblyDefinition assembly, XPathNodeIterator iterator) + { + if (IsExcluded (iterator.Current)) + return; + + Tracer.Push (assembly); + if (GetTypePreserve (iterator.Current) == TypePreserve.All) { + foreach (var type in assembly.MainModule.Types) + MarkAndPreserveAll (type); + } else { + ProcessTypes (assembly, iterator.Current.SelectChildren ("type", _ns)); + ProcessNamespaces (assembly, iterator.Current.SelectChildren ("namespace", _ns)); + } + Tracer.Pop (); + } + + void ProcessNamespaces (AssemblyDefinition assembly, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) { + string fullname = GetFullName (iterator.Current); + foreach (TypeDefinition type in assembly.MainModule.Types) { + if (type.Namespace != fullname) + continue; + + MarkAndPreserveAll (type); + } + } + } + + void MarkAndPreserveAll (TypeDefinition type) + { + Annotations.MarkAndPush (type); + Annotations.SetPreserve (type, TypePreserve.All); + + if (!type.HasNestedTypes) { + Tracer.Pop (); + return; + } + + foreach (TypeDefinition nested in type.NestedTypes) + MarkAndPreserveAll (nested); + + Tracer.Pop (); + } + + void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) { + XPathNavigator nav = iterator.Current; + + string fullname = GetFullName (nav); + + if (IsTypePattern (fullname)) { + ProcessTypePattern (fullname, assembly, nav); + continue; + } + + TypeDefinition type = assembly.MainModule.GetType (fullname); + + if (type == null) { + if (assembly.MainModule.HasExportedTypes) { + foreach (var exported in assembly.MainModule.ExportedTypes) { + if (fullname == exported.FullName) { + Tracer.Push (exported); + MarkingHelpers.MarkExportedType (exported, assembly.MainModule); + var resolvedExternal = exported.Resolve (); + Tracer.Pop (); + if (resolvedExternal != null) { + type = resolvedExternal; + break; + } + } + } + } + } + + if (type == null) + continue; + + ProcessType (type, nav); + } + } + + static bool IsTypePattern (string fullname) + { + return fullname.IndexOf ("*") != -1; + } + + static Regex CreateRegexFromPattern (string pattern) + { + return new Regex (pattern.Replace (".", @"\.").Replace ("*", "(.*)")); + } + + void MatchType (TypeDefinition type, Regex regex, XPathNavigator nav) + { + if (regex.Match (type.FullName).Success) + ProcessType (type, nav); + + if (!type.HasNestedTypes) + return; + + foreach (var nt in type.NestedTypes) + MatchType (nt, regex, nav); + } + + void MatchExportedType (ExportedType exportedType, ModuleDefinition module, Regex regex, XPathNavigator nav) + { + if (regex.Match (exportedType.FullName).Success) { + MarkingHelpers.MarkExportedType (exportedType, module); + TypeDefinition type = exportedType.Resolve (); + if (type != null) { + ProcessType (type, nav); + } + } + } + + + void ProcessTypePattern (string fullname, AssemblyDefinition assembly, XPathNavigator nav) + { + Regex regex = CreateRegexFromPattern (fullname); + + foreach (TypeDefinition type in assembly.MainModule.Types) { + MatchType (type, regex, nav); + } + + if (assembly.MainModule.HasExportedTypes) { + foreach (var exported in assembly.MainModule.ExportedTypes) { + MatchExportedType (exported, assembly.MainModule, regex, nav); + } + } + } + + protected virtual void ProcessType (TypeDefinition type, XPathNavigator nav) + { + if (IsExcluded (nav)) + return; + + TypePreserve preserve = GetTypePreserve (nav); + + if (!IsRequired (nav)) { + Annotations.SetPreserve (type, preserve); + return; + } + + if (Annotations.IsMarked (type)) { + var existingLevel = Annotations.TryGetPreserve (type, out TypePreserve existingPreserve) ? existingPreserve : TypePreserve.Nothing; + var duplicateLevel = preserve != TypePreserve.Nothing ? preserve : nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All; + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {type.FullName} ({existingLevel}). Duplicate uses ({duplicateLevel})"); + } + + Annotations.MarkAndPush (type); + Tracer.AddDirectDependency (this, type); + + if (type.IsNested) { + var parent = type; + while (parent.IsNested) { + parent = parent.DeclaringType; + Annotations.Mark (parent); + } + } + + if (preserve != TypePreserve.Nothing) + Annotations.SetPreserve (type, preserve); + + if (nav.HasChildren) { + MarkSelectedFields (nav, type); + MarkSelectedMethods (nav, type); + MarkSelectedEvents (nav, type); + MarkSelectedProperties (nav, type); + } + Tracer.Pop (); + } + + void MarkSelectedFields (XPathNavigator nav, TypeDefinition type) + { + XPathNodeIterator fields = nav.SelectChildren ("field", _ns); + if (fields.Count == 0) + return; + + ProcessFields (type, fields); + } + + void MarkSelectedMethods (XPathNavigator nav, TypeDefinition type) + { + XPathNodeIterator methods = nav.SelectChildren ("method", _ns); + if (methods.Count == 0) + return; + + ProcessMethods (type, methods); + } + + void MarkSelectedEvents (XPathNavigator nav, TypeDefinition type) + { + XPathNodeIterator events = nav.SelectChildren ("event", _ns); + if (events.Count == 0) + return; + + ProcessEvents (type, events); + } + + void MarkSelectedProperties (XPathNavigator nav, TypeDefinition type) + { + XPathNodeIterator properties = nav.SelectChildren ("property", _ns); + if (properties.Count == 0) + return; + + ProcessProperties (type, properties); + } + + static TypePreserve GetTypePreserve (XPathNavigator nav) + { + string attribute = GetAttribute (nav, _preserve); + if (string.IsNullOrEmpty (attribute)) + return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All; + + TypePreserve result; + if (Enum.TryParse (attribute, true, out result)) + return result; + return TypePreserve.Nothing; + } + + void ProcessFields (TypeDefinition type, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) + ProcessField (type, iterator); + } + + protected virtual void ProcessField (TypeDefinition type, XPathNodeIterator iterator) + { + if (IsExcluded (iterator.Current)) + return; + + string value = GetSignature (iterator.Current); + if (!String.IsNullOrEmpty (value)) + ProcessFieldSignature (type, value); + + value = GetAttribute (iterator.Current, "name"); + if (!String.IsNullOrEmpty (value)) + ProcessFieldName (type, value); + } + + void ProcessFieldSignature (TypeDefinition type, string signature) + { + FieldDefinition field = GetField (type, signature); + MarkField (type, field, signature); + } + + void MarkField (TypeDefinition type, FieldDefinition field, string signature) + { + if (field != null) { + if (Annotations.IsMarked (field)) + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {field.FullName}"); + + Annotations.Mark (field); + } else { + AddUnresolveMarker (string.Format ("T: {0}; F: {1}", type, signature)); + } + } + + void ProcessFieldName (TypeDefinition type, string name) + { + if (!type.HasFields) + return; + + foreach (FieldDefinition field in type.Fields) + if (field.Name == name) + MarkField (type, field, name); + } + + protected static FieldDefinition GetField (TypeDefinition type, string signature) + { + if (!type.HasFields) + return null; + + foreach (FieldDefinition field in type.Fields) + if (signature == GetFieldSignature (field)) + return field; + + return null; + } + + static string GetFieldSignature (FieldDefinition field) + { + return field.FieldType.FullName + " " + field.Name; + } + + void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) + ProcessMethod (type, iterator); + } + + protected virtual void ProcessMethod (TypeDefinition type, XPathNodeIterator iterator) + { + if (IsExcluded (iterator.Current)) + return; + + string value = GetSignature (iterator.Current); + if (!String.IsNullOrEmpty (value)) + ProcessMethodSignature (type, value); + + value = GetAttribute (iterator.Current, "name"); + if (!String.IsNullOrEmpty (value)) + ProcessMethodName (type, value); + } + + void ProcessMethodSignature (TypeDefinition type, string signature) + { + MethodDefinition meth = GetMethod (type, signature); + MarkMethod (type, meth, signature); + } + + void MarkMethod (TypeDefinition type, MethodDefinition method, string signature) + { + if (method != null) { + MarkMethod (method); + } else + AddUnresolveMarker (string.Format ("T: {0}; M: {1}", type, signature)); + } + + void MarkMethod (MethodDefinition method) + { + if (Annotations.IsMarked (method)) + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {method.FullName}"); + + Annotations.Mark (method); + Annotations.MarkIndirectlyCalledMethod (method); + Tracer.AddDirectDependency (this, method); + Annotations.SetAction (method, MethodAction.Parse); + } + + void MarkMethodIfNotNull (MethodDefinition method) + { + if (method == null) + return; + + MarkMethod (method); + } + + void ProcessMethodName (TypeDefinition type, string name) + { + if (!type.HasMethods) + return; + + foreach (MethodDefinition method in type.Methods) + if (name == method.Name) + MarkMethod (type, method, name); + } + + protected static MethodDefinition GetMethod (TypeDefinition type, string signature) + { + if (type.HasMethods) + foreach (MethodDefinition meth in type.Methods) + if (signature == GetMethodSignature (meth, false)) + return meth; + + return null; + } + + public static string GetMethodSignature (MethodDefinition meth, bool includeGenericParameters) + { + StringBuilder sb = new StringBuilder (); + sb.Append (meth.ReturnType.FullName); + sb.Append (" "); + sb.Append (meth.Name); + if (includeGenericParameters && meth.HasGenericParameters) { + sb.Append ("`"); + sb.Append (meth.GenericParameters.Count); + } + + sb.Append ("("); + if (meth.HasParameters) { + for (int i = 0; i < meth.Parameters.Count; i++) { + if (i > 0) + sb.Append (","); + + sb.Append (meth.Parameters [i].ParameterType.FullName); + } + } + sb.Append (")"); + return sb.ToString (); + } + + void ProcessEvents (TypeDefinition type, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) + ProcessEvent (type, iterator); + } + + protected virtual void ProcessEvent (TypeDefinition type, XPathNodeIterator iterator) + { + if (IsExcluded (iterator.Current)) + return; + + string value = GetSignature (iterator.Current); + if (!String.IsNullOrEmpty (value)) + ProcessEventSignature (type, value); + + value = GetAttribute (iterator.Current, "name"); + if (!String.IsNullOrEmpty (value)) + ProcessEventName (type, value); + } + + void ProcessEventSignature (TypeDefinition type, string signature) + { + EventDefinition @event = GetEvent (type, signature); + MarkEvent (type, @event, signature); + } + + void MarkEvent (TypeDefinition type, EventDefinition @event, string signature) + { + if (@event != null) { + if (Annotations.IsMarked (@event)) + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {@event.FullName}"); + + Annotations.Mark (@event); + + MarkMethod (@event.AddMethod); + MarkMethod (@event.RemoveMethod); + MarkMethodIfNotNull (@event.InvokeMethod); + } else + AddUnresolveMarker (string.Format ("T: {0}; E: {1}", type, signature)); + } + + void ProcessEventName (TypeDefinition type, string name) + { + if (!type.HasEvents) + return; + + foreach (EventDefinition @event in type.Events) + if (@event.Name == name) + MarkEvent (type, @event, name); + } + + protected static EventDefinition GetEvent (TypeDefinition type, string signature) + { + if (!type.HasEvents) + return null; + + foreach (EventDefinition @event in type.Events) + if (signature == GetEventSignature (@event)) + return @event; + + return null; + } + + static string GetEventSignature (EventDefinition @event) + { + return @event.EventType.FullName + " " + @event.Name; + } + + void ProcessProperties (TypeDefinition type, XPathNodeIterator iterator) + { + while (iterator.MoveNext ()) + ProcessProperty (type, iterator); + } + + protected virtual void ProcessProperty (TypeDefinition type, XPathNodeIterator iterator) + { + if (IsExcluded (iterator.Current)) + return; + + string value = GetSignature (iterator.Current); + if (!String.IsNullOrEmpty (value)) + ProcessPropertySignature (type, value, GetAccessors (iterator.Current)); + + value = GetAttribute (iterator.Current, "name"); + if (!String.IsNullOrEmpty (value)) + ProcessPropertyName (type, value, _accessorsAll); + } + + void ProcessPropertySignature (TypeDefinition type, string signature, string[] accessors) + { + PropertyDefinition property = GetProperty (type, signature); + MarkProperty (type, property, signature, accessors); + } + + void MarkProperty (TypeDefinition type, PropertyDefinition property, string signature, string[] accessors) + { + if (property != null) { + if (Annotations.IsMarked (property)) + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {property.FullName}"); + + Annotations.Mark (property); + + MarkPropertyAccessors (type, property, accessors); + } else + AddUnresolveMarker (string.Format ("T: {0}; P: {1}", type, signature)); + } + + void MarkPropertyAccessors (TypeDefinition type, PropertyDefinition property, string[] accessors) + { + if (Array.IndexOf (accessors, "all") >= 0) { + MarkMethodIfNotNull (property.GetMethod); + MarkMethodIfNotNull (property.SetMethod); + + return; + } + if (property.GetMethod != null + && Array.IndexOf (accessors, "get") >= 0) + MarkMethod (property.GetMethod); + else if (property.GetMethod == null) + AddUnresolveMarker (string.Format ("T: {0}' M: {1} get_{2}", type, property.PropertyType, property.Name)); + + if (property.SetMethod != null + && Array.IndexOf (accessors, "set") >= 0) + MarkMethod (property.SetMethod); + else if (property.SetMethod == null) + AddUnresolveMarker (string.Format ("T: {0}' M: System.Void set_{2} ({1})", type, property.PropertyType, property.Name)); + } + + void ProcessPropertyName (TypeDefinition type, string name, string[] accessors) + { + if (!type.HasProperties) + return; + + foreach (PropertyDefinition property in type.Properties) + if (property.Name == name) + MarkProperty (type, property, name, accessors); + } + + protected static PropertyDefinition GetProperty (TypeDefinition type, string signature) + { + if (!type.HasProperties) + return null; + + foreach (PropertyDefinition property in type.Properties) + if (signature == GetPropertySignature (property)) + return property; + + return null; + } + + static string GetPropertySignature (PropertyDefinition property) + { + return property.PropertyType.FullName + " " + property.Name; + } + + protected AssemblyDefinition GetAssembly (LinkContext context, AssemblyNameReference assemblyName) + { + var assembly = context.Resolve (assemblyName); + ProcessReferences (assembly, context); + return assembly; + } + + protected virtual AssemblyNameReference GetAssemblyName (XPathNavigator nav) + { + return AssemblyNameReference.Parse (GetFullName (nav)); + } + + static void ProcessReferences (AssemblyDefinition assembly, LinkContext context) + { + context.ResolveReferences (assembly); + } + + static bool IsRequired (XPathNavigator nav) + { + string attribute = GetAttribute (nav, _required); + if (attribute == null || attribute.Length == 0) + return true; + + bool result; + if (bool.TryParse (attribute, out result)) + return result; + return false; + } + + protected static string GetSignature (XPathNavigator nav) + { + return GetAttribute (nav, _signature); + } + + static string GetFullName (XPathNavigator nav) + { + return GetAttribute (nav, _fullname); + } + + protected static string[] GetAccessors (XPathNavigator nav) + { + string accessorsValue = GetAttribute (nav, _accessors); + + if (accessorsValue != null) { + string[] accessors = accessorsValue.Split ( + _accessorsSep, StringSplitOptions.RemoveEmptyEntries); + + if (accessors.Length > 0) { + for (int i = 0; i < accessors.Length; ++i) + accessors[i] = accessors[i].ToLower (); + + return accessors; + } + } + return _accessorsAll; + } + + protected static string GetAttribute (XPathNavigator nav, string attribute) + { + return nav.GetAttribute (attribute, _ns); + } + + protected virtual bool IsExcluded (XPathNavigator nav) + { + var value = GetAttribute (nav, "feature"); + if (string.IsNullOrEmpty (value)) + return false; + + return Context.IsFeatureExcluded (value); + } + + + public override string ToString () + { + return "ResolveFromXmlStep: " + _xmlDocumentLocation; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs new file mode 100644 index 000000000000..49503f93692c --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs @@ -0,0 +1,57 @@ +// +// ResolveStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.Linker.Steps { + + public abstract class ResolveStep : BaseStep { + + readonly List _unResolved; + + protected ResolveStep () + { + _unResolved = new List (); + } + + public bool AllMarkerResolved + { + get { return _unResolved.Count == 0; } + } + + public string [] GetUnresolvedMarkers () + { + return _unResolved.ToArray (); + } + + protected void AddUnresolveMarker (string signature) + { + _unResolved.Add (signature); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs new file mode 100644 index 000000000000..8bcf11175e0f --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs @@ -0,0 +1,715 @@ +// +// SweepStep.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// (C) 2007 Novell, 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.Collections.Generic; +using System.Linq; +using Mono.Cecil; +using Mono.Collections.Generic; +using Mono.Cecil.Cil; + +namespace Mono.Linker.Steps { + + public class SweepStep : BaseStep + { + AssemblyDefinition [] assemblies; + readonly bool sweepSymbols; + readonly HashSet BypassNGenToSave = new HashSet (); + + public SweepStep (bool sweepSymbols = true) + { + this.sweepSymbols = sweepSymbols; + } + + protected override void Process () + { + assemblies = Context.Annotations.GetAssemblies ().ToArray (); + + foreach (var assembly in assemblies) { + RemoveUnusedAssembly (assembly); + } + + foreach (var assembly in assemblies) { + ProcessAssemblyAction (assembly); + } + } + + void RemoveUnusedAssembly (AssemblyDefinition assembly) + { + switch (Annotations.GetAction (assembly)) { + case AssemblyAction.AddBypassNGenUsed: + case AssemblyAction.CopyUsed: + case AssemblyAction.Link: + if (!IsUsedAssembly (assembly)) + RemoveAssembly (assembly); + + break; + } + } + + protected void ProcessAssemblyAction (AssemblyDefinition assembly) + { + switch (Annotations.GetAction (assembly)) { + case AssemblyAction.AddBypassNGenUsed: + Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen); + goto case AssemblyAction.AddBypassNGen; + + case AssemblyAction.AddBypassNGen: + // FIXME: AddBypassNGen is just wrong, it should not be action as we need to + // turn it to Action.Save here to e.g. correctly update debug symbols + if (!Context.KeepTypeForwarderOnlyAssemblies || BypassNGenToSave.Contains (assembly)) { + goto case AssemblyAction.Save; + } + + break; + + case AssemblyAction.CopyUsed: + Annotations.SetAction (assembly, AssemblyAction.Copy); + goto case AssemblyAction.Copy; + + case AssemblyAction.Copy: + // + // Facade assemblies can have unused forwarders pointing to + // removed type (when facades are kept) + // + // main.exe -> facade.dll -> lib.dll + // link | copy | link + // + // when main.exe has unused reference to type in lib.dll + // + if (SweepTypeForwarders (assembly)) + Annotations.SetAction (assembly, AssemblyAction.Save); + + break; + + case AssemblyAction.Link: + SweepAssembly (assembly); + break; + + case AssemblyAction.Save: + // + // Save means we need to rewrite the assembly due to removed assembly + // reference. We do any additional removed assembly reference clean up here + // + UpdateForwardedTypesScope (assembly); + UpdateCustomAttributesTypesScopes (assembly); + SweepTypeForwarders (assembly); + break; + } + } + + protected virtual void SweepAssembly (AssemblyDefinition assembly) + { + var types = new List (); + + foreach (TypeDefinition type in assembly.MainModule.Types) { + if (Annotations.IsMarked (type)) { + SweepType (type); + types.Add (type); + continue; + } + + if (type.Name == "") + types.Add (type); + else + ElementRemoved (type); + } + + assembly.MainModule.Types.Clear (); + foreach (TypeDefinition type in types) + assembly.MainModule.Types.Add (type); + + SweepResources (assembly); + SweepCustomAttributes (assembly); + + foreach (var module in assembly.Modules) + SweepCustomAttributes (module); + + SweepTypeForwarders (assembly); + + UpdateForwardedTypesScope (assembly); + } + + bool IsUsedAssembly (AssemblyDefinition assembly) + { + if (IsMarkedAssembly (assembly)) + return true; + + if (assembly.MainModule.HasExportedTypes && Context.KeepTypeForwarderOnlyAssemblies) + return true; + + return false; + } + + bool IsMarkedAssembly (AssemblyDefinition assembly) + { + return Annotations.IsMarked (assembly.MainModule); + } + + protected virtual void RemoveAssembly (AssemblyDefinition assembly) + { + Annotations.SetAction (assembly, AssemblyAction.Delete); + + foreach (var a in assemblies) { + switch (Annotations.GetAction (a)) { + case AssemblyAction.Skip: + case AssemblyAction.Delete: + continue; + } + + SweepReferences (a, assembly); + } + } + + void SweepResources (AssemblyDefinition assembly) + { + var resourcesToRemove = Annotations.GetResourcesToRemove (assembly); + if (resourcesToRemove != null) { + var resources = assembly.MainModule.Resources; + + for (int i = 0; i < resources.Count; i++) { + var resource = resources [i] as EmbeddedResource; + if (resource == null) + continue; + + if (resourcesToRemove.Contains (resource.Name)) + resources.RemoveAt (i--); + } + } + } + + void SweepReferences (AssemblyDefinition assembly, AssemblyDefinition referenceToRemove) + { + if (assembly == referenceToRemove) + return; + + bool reference_removed = false; + + var references = assembly.MainModule.AssemblyReferences; + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + + AssemblyDefinition ad = Context.Resolver.Resolve (reference); + if (ad == null || !AreSameReference (ad.Name, referenceToRemove.Name)) + continue; + + ReferenceRemoved (assembly, reference); + references.RemoveAt (i--); + reference_removed = true; + } + + if (reference_removed) { + switch (Annotations.GetAction (assembly)) { + case AssemblyAction.CopyUsed: + if (IsUsedAssembly (assembly)) { + goto case AssemblyAction.Copy; + } + break; + + case AssemblyAction.Copy: + // + // Assembly has a reference to another assembly which has been fully removed. This can + // happen when for example the reference assembly is 'copy-used' and it's not needed. + // + // or + // + // Assembly can contain type references with + // type forwarders to deleted assembly (facade) when + // facade assemblies are not kept. For that reason we need to + // rewrite the copy to save to update the scopes not to point + // forwarding assembly (facade). + // + // foo.dll -> facade.dll -> lib.dll + // copy | copy (delete) | link + // + Annotations.SetAction (assembly, AssemblyAction.Save); + break; + + case AssemblyAction.AddBypassNGenUsed: + if (IsUsedAssembly (assembly)) { + Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen); + goto case AssemblyAction.AddBypassNGen; + } + break; + + case AssemblyAction.AddBypassNGen: + BypassNGenToSave.Add (assembly); + break; + } + } + } + + bool SweepTypeForwarders (AssemblyDefinition assembly) + { + if (assembly.MainModule.HasExportedTypes) { + return SweepCollectionMetadata (assembly.MainModule.ExportedTypes); + } + + return false; + } + + void UpdateForwardedTypesScope (AssemblyDefinition assembly) + { + var changed_types = new Dictionary (); + + foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) { + if (tr.IsWindowsRuntimeProjection) + continue; + + TypeDefinition td; + try { + td = tr.Resolve (); + } catch (AssemblyResolutionException) { + // Don't crash on unresolved assembly + continue; + } + + // 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)) + continue; + + IMetadataScope scope = assembly.MainModule.ImportReference (td).Scope; + if (tr.Scope != scope) + changed_types.Add (tr, scope); + } + + // + // Resolved everything first before updating scopes. + // If we set the scope to null, then calling Resolve() on any of its + // nested types would crash. + // + foreach (var e in changed_types) { + e.Key.Scope = e.Value; + } + + if (assembly.MainModule.HasExportedTypes) { + foreach (var et in assembly.MainModule.ExportedTypes) { + var td = et.Resolve (); + if (td == null) + continue; + + et.Scope = assembly.MainModule.ImportReference (td).Scope; + } + } + } + + static void UpdateCustomAttributesTypesScopes (AssemblyDefinition assembly) + { + UpdateCustomAttributesTypesScopes ((ICustomAttributeProvider) assembly); + + foreach (var module in assembly.Modules) + UpdateCustomAttributesTypesScopes (module); + + foreach (var type in assembly.MainModule.Types) + UpdateCustomAttributesTypesScopes (type); + } + + static void UpdateCustomAttributesTypesScopes (TypeDefinition typeDefinition) + { + UpdateCustomAttributesTypesScopes ((ICustomAttributeProvider)typeDefinition); + + if (typeDefinition.HasEvents) + UpdateCustomAttributesTypesScopes (typeDefinition.Events); + + if (typeDefinition.HasFields) + UpdateCustomAttributesTypesScopes (typeDefinition.Fields); + + if (typeDefinition.HasMethods) + UpdateCustomAttributesTypesScopes (typeDefinition.Methods); + + if (typeDefinition.HasProperties) + UpdateCustomAttributesTypesScopes (typeDefinition.Properties); + + if (typeDefinition.HasGenericParameters) + UpdateCustomAttributesTypesScopes (typeDefinition.GenericParameters); + + if (typeDefinition.HasNestedTypes) { + foreach (var nestedType in typeDefinition.NestedTypes) { + UpdateCustomAttributesTypesScopes (nestedType); + } + } + } + + static void UpdateCustomAttributesTypesScopes (Collection providers) where T : ICustomAttributeProvider + { + foreach (var provider in providers) + UpdateCustomAttributesTypesScopes (provider); + } + + static void UpdateCustomAttributesTypesScopes (Collection genericParameters) + { + foreach (var gp in genericParameters) { + UpdateCustomAttributesTypesScopes (gp); + + if (gp.HasConstraints) + UpdateCustomAttributesTypesScopes (gp.Constraints); + } + } + + static void UpdateCustomAttributesTypesScopes (ICustomAttributeProvider customAttributeProvider) + { + if (!customAttributeProvider.HasCustomAttributes) + return; + + foreach (var ca in customAttributeProvider.CustomAttributes) + UpdateForwardedTypesScope (ca); + } + + static void UpdateForwardedTypesScope (CustomAttribute attribute) + { + AssemblyDefinition assembly = attribute.Constructor.Module.Assembly; + + if (attribute.HasConstructorArguments) { + foreach (var ca in attribute.ConstructorArguments) + UpdateForwardedTypesScope (ca, assembly); + } + + if (attribute.HasFields) { + foreach (var field in attribute.Fields) + UpdateForwardedTypesScope (field.Argument, assembly); + } + + if (attribute.HasProperties) { + foreach (var property in attribute.Properties) + UpdateForwardedTypesScope (property.Argument, assembly); + } + } + + static void UpdateForwardedTypesScope (CustomAttributeArgument attributeArgument, AssemblyDefinition assembly) + { + UpdateTypeScope (attributeArgument.Type, assembly); + + switch (attributeArgument.Value) { + case TypeReference tr: + UpdateTypeScope (tr, assembly); + break; + case CustomAttributeArgument caa: + UpdateForwardedTypesScope (caa, assembly); + break; + case CustomAttributeArgument[] array: + foreach (var item in array) + UpdateForwardedTypesScope (item, assembly); + break; + } + } + + static void UpdateTypeScope (TypeReference type, AssemblyDefinition assembly) + { + // Can't update the scope of windows runtime projections + if (type.IsWindowsRuntimeProjection) + return; + + if (type is GenericInstanceType git && git.HasGenericArguments) { + UpdateTypeScope (git.ElementType, assembly); + foreach (var ga in git.GenericArguments) + UpdateTypeScope (ga, assembly); + return; + } + + if (type is ArrayType at) { + UpdateTypeScope (at.ElementType, assembly); + return; + } + + TypeDefinition td = type.Resolve (); + if (td == null) + return; + + IMetadataScope scope = assembly.MainModule.ImportReference (td).Scope; + if (type.Scope != scope) + type.Scope = td.Scope; + } + + protected virtual void SweepType (TypeDefinition type) + { + if (type.HasFields) + SweepCollectionWithCustomAttributes (type.Fields); + + if (type.HasMethods) + SweepMethods (type.Methods); + + if (type.HasNestedTypes) + SweepNestedTypes (type); + + if (type.HasInterfaces) + SweepInterfaces (type); + + if (type.HasCustomAttributes) + SweepCustomAttributes (type); + + if (type.HasGenericParameters) + SweepGenericParameters (type.GenericParameters); + + if (type.HasProperties) + SweepCustomAttributeCollection (type.Properties); + + if (type.HasEvents) + SweepCustomAttributeCollection (type.Events); + + if (type.HasFields && !type.IsBeforeFieldInit && !Annotations.HasPreservedStaticCtor (type) && !type.IsEnum) + type.IsBeforeFieldInit = true; + } + + protected void SweepNestedTypes (TypeDefinition type) + { + for (int i = 0; i < type.NestedTypes.Count; i++) { + var nested = type.NestedTypes [i]; + if (Annotations.IsMarked (nested)) { + SweepType (nested); + } else { + ElementRemoved (type.NestedTypes [i]); + type.NestedTypes.RemoveAt (i--); + } + } + } + + protected void SweepInterfaces (TypeDefinition type) + { + for (int i = type.Interfaces.Count - 1; i >= 0; i--) { + var iface = type.Interfaces [i]; + if (Annotations.IsMarked (iface)) { + SweepCustomAttributes (iface); + continue; + } + InterfaceRemoved (type, iface); + type.Interfaces.RemoveAt (i); + } + } + + protected void SweepGenericParameters (Collection genericParameters) + { + foreach (var gp in genericParameters) { + SweepCustomAttributes (gp); + + if (gp.HasConstraints) + SweepCustomAttributeCollection (gp.Constraints); + } + } + + protected void SweepCustomAttributes (TypeDefinition type) + { + var removed = SweepCustomAttributes (type as ICustomAttributeProvider); + + if (ShouldSetHasSecurityToFalse (type, type, type.HasSecurity, removed)) + type.HasSecurity = false; + } + + protected void SweepCustomAttributes (MethodDefinition method) + { + var removed = SweepCustomAttributes (method as ICustomAttributeProvider); + + if (ShouldSetHasSecurityToFalse (method, method, method.HasSecurity, removed)) + method.HasSecurity = false; + } + + bool ShouldSetHasSecurityToFalse (ISecurityDeclarationProvider providerAsSecurity, ICustomAttributeProvider provider, bool existingHasSecurity, IList removedAttributes) + { + if (existingHasSecurity && removedAttributes.Count > 0 && !providerAsSecurity.HasSecurityDeclarations) { + // If the method or type had security before and all attributes were removed, or no remaining attributes are security attributes, + // then we need to set HasSecurity to false + if (provider.CustomAttributes.Count == 0 || provider.CustomAttributes.All (attr => !IsSecurityAttributeType (attr.AttributeType.Resolve ()))) + return true; + } + + return false; + } + + static bool IsSecurityAttributeType (TypeDefinition definition) + { + if (definition == null) + return false; + + if (definition.Namespace == "System.Security") { + switch (definition.FullName) { + // This seems to be one attribute in the System.Security namespace that doesn't count + // as an attribute that requires HasSecurity to be true + case "System.Security.SecurityCriticalAttribute": + return false; + } + + return true; + } + + if (definition.BaseType == null) + return false; + + return IsSecurityAttributeType (definition.BaseType.Resolve ()); + } + + protected IList SweepCustomAttributes (ICustomAttributeProvider provider) + { + var removed = new List(); + + for (int i = provider.CustomAttributes.Count - 1; i >= 0; i--) { + var attribute = provider.CustomAttributes [i]; + if (Annotations.IsMarked (attribute)) { + UpdateForwardedTypesScope (attribute); + } else { + CustomAttributeUsageRemoved (provider, attribute); + removed.Add (provider.CustomAttributes [i]); + provider.CustomAttributes.RemoveAt (i); + } + } + + return removed; + } + + protected void SweepCustomAttributeCollection (Collection providers) where T : ICustomAttributeProvider + { + foreach (var provider in providers) + SweepCustomAttributes (provider); + } + + protected virtual void SweepMethods (Collection methods) + { + SweepCollectionWithCustomAttributes (methods); + if (sweepSymbols) + SweepDebugInfo (methods); + + foreach (var method in methods) { + if (method.HasGenericParameters) + SweepGenericParameters (method.GenericParameters); + + SweepCustomAttributes (method.MethodReturnType); + + if (!method.HasParameters) + continue; + + foreach (var parameter in method.Parameters) + SweepCustomAttributes (parameter); + } + } + + void SweepDebugInfo (Collection methods) + { + List sweptScopes = null; + foreach (var m in methods) { + if (m.DebugInformation == null) + continue; + + var scope = m.DebugInformation.Scope; + if (scope == null) + continue; + + if (sweptScopes == null) { + sweptScopes = new List (); + } else if (sweptScopes.Contains (scope)) { + continue; + } + + sweptScopes.Add (scope); + + if (scope.HasConstants) { + var constants = scope.Constants; + for (int i = 0; i < constants.Count; ++i) { + if (!Annotations.IsMarked (constants [i].ConstantType)) + constants.RemoveAt (i--); + } + } + + var import = scope.Import; + while (import != null) { + if (import.HasTargets) { + var targets = import.Targets; + for (int i = 0; i < targets.Count; ++i) { + var ttype = targets [i].Type; + if (ttype != null && !Annotations.IsMarked (ttype)) + targets.RemoveAt (i--); + + // TODO: Clear also AssemblyReference and Namespace when not marked + } + } + + import = import.Parent; + } + } + } + + protected void SweepCollectionWithCustomAttributes (IList list) where T : ICustomAttributeProvider + { + for (int i = 0; i < list.Count; i++) + if (ShouldRemove (list [i])) { + ElementRemoved (list [i]); + list.RemoveAt (i--); + } else { + SweepCustomAttributes (list [i]); + } + } + + protected bool SweepCollectionMetadata (IList list) where T : IMetadataTokenProvider + { + bool removed = false; + + for (int i = 0; i < list.Count; i++) { + if (ShouldRemove (list [i])) { + ElementRemoved (list [i]); + list.RemoveAt (i--); + removed = true; + } + } + + return removed; + } + + protected virtual bool ShouldRemove (T element) where T : IMetadataTokenProvider + { + return !Annotations.IsMarked (element); + } + + static bool AreSameReference (AssemblyNameReference a, AssemblyNameReference b) + { + if (a == b) + return true; + + if (a.Name != b.Name) + return false; + + if (a.Version > b.Version) + return false; + + return true; + } + + protected virtual void ElementRemoved (IMetadataTokenProvider element) + { + } + + protected virtual void ReferenceRemoved (AssemblyDefinition assembly, AssemblyNameReference reference) + { + } + + protected virtual void InterfaceRemoved (TypeDefinition type, InterfaceImplementation iface) + { + } + + protected virtual void CustomAttributeUsageRemoved (ICustomAttributeProvider provider, CustomAttribute attribute) + { + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs new file mode 100644 index 000000000000..32727fa65e61 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs @@ -0,0 +1,371 @@ +// +// TypeMapStep.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2009 Novell, 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.Collections.Generic; +using Mono.Cecil; + +namespace Mono.Linker.Steps { + + public class TypeMapStep : BaseStep { + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + foreach (TypeDefinition type in assembly.MainModule.Types) + MapType (type); + } + + protected virtual void MapType (TypeDefinition type) + { + MapVirtualMethods (type); + MapInterfaceMethodsInTypeHierarchy (type); + MapInterfaceHierarchy (type); + MapBaseTypeHierarchy (type); + + if (!type.HasNestedTypes) + return; + + foreach (var nested in type.NestedTypes) + MapType (nested); + } + + void MapInterfaceHierarchy (TypeDefinition type) + { + if (!type.IsInterface || !type.HasInterfaces) + return; + + foreach (var iface in type.Interfaces) { + var resolved = iface.InterfaceType.Resolve (); + if (resolved == null) + continue; + + Annotations.AddDerivedInterfaceForInterface (resolved, type); + } + } + + void MapInterfaceMethodsInTypeHierarchy (TypeDefinition type) + { + if (!type.HasInterfaces) + return; + + foreach (var @interface in type.Interfaces) { + var interfaceType = @interface.InterfaceType; + var iface = interfaceType.Resolve (); + if (iface == null || !iface.HasMethods) + continue; + + foreach (MethodDefinition interfaceMethod in iface.Methods) { + if (TryMatchMethod (type, interfaceMethod) != null) + continue; + + var @base = GetBaseMethodInTypeHierarchy (type, interfaceMethod); + if (@base != null) + AnnotateMethods (interfaceMethod, @base, @interface); + + if (interfaceType is GenericInstanceType genericInterfaceInstance) { + var genericContext = new Inflater.GenericContext (genericInterfaceInstance, null); + var baseInflated = GetBaseInflatedInterfaceMethodInTypeHierarchy (genericContext, type, interfaceMethod); + if (baseInflated != null) + Annotations.AddOverride (interfaceMethod, baseInflated, @interface); + } + } + } + } + + static MethodReference CreateGenericInstanceCandidate (Inflater.GenericContext context, TypeDefinition candidateType, MethodDefinition interfaceMethod) + { + var methodReference = new MethodReference (interfaceMethod.Name, interfaceMethod.ReturnType, candidateType) {HasThis = interfaceMethod.HasThis}; + + foreach (var genericMethodParameter in interfaceMethod.GenericParameters) + methodReference.GenericParameters.Add (new GenericParameter (genericMethodParameter.Name, methodReference)); + + if (interfaceMethod.ReturnType.IsGenericParameter || interfaceMethod.ReturnType.IsGenericInstance) + methodReference.ReturnType = Inflater.InflateType (context, interfaceMethod.ReturnType); + + foreach (var p in interfaceMethod.Parameters) { + var parameterType = p.ParameterType; + if (parameterType.IsGenericParameter || parameterType.IsGenericInstance) + parameterType = Inflater.InflateType (context, parameterType); + + methodReference.Parameters.Add (new ParameterDefinition (p.Name, p.Attributes, parameterType)); + } + + return methodReference; + } + + void MapVirtualMethods (TypeDefinition type) + { + if (!type.HasMethods) + return; + + foreach (MethodDefinition method in type.Methods) { + if (!method.IsVirtual) + continue; + + MapVirtualMethod (method); + + if (method.HasOverrides) + MapOverrides (method); + } + } + + void MapVirtualMethod (MethodDefinition method) + { + MapVirtualBaseMethod (method); + MapVirtualInterfaceMethod (method); + } + + void MapVirtualBaseMethod (MethodDefinition method) + { + MethodDefinition @base = GetBaseMethodInTypeHierarchy (method); + if (@base == null) + return; + + AnnotateMethods (@base, method); + } + + void MapVirtualInterfaceMethod (MethodDefinition method) + { + foreach (MethodDefinition @base in GetBaseMethodsInInterfaceHierarchy (method)) + AnnotateMethods (@base, method); + } + + void MapOverrides (MethodDefinition method) + { + foreach (MethodReference override_ref in method.Overrides) { + MethodDefinition @override = override_ref.Resolve (); + if (@override == null) + continue; + + AnnotateMethods (@override, method); + } + } + + void MapBaseTypeHierarchy (TypeDefinition type) + { + if (!type.IsClass) + return; + + var bases = new List (); + var current = type.BaseType; + + while (current != null) { + var resolved = current.Resolve (); + if (resolved == null) + break; + + // Exclude Object. That's implied and adding it to the list will just lead to lots of extra unnecessary processing + if (resolved.BaseType == null) + break; + + bases.Add (resolved); + current = resolved.BaseType; + } + + Annotations.SetClassHierarchy (type, bases); + } + + void AnnotateMethods (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) + { + Annotations.AddBaseMethod (@override, @base); + Annotations.AddOverride (@base, @override, matchingInterfaceImplementation); + } + + static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) + { + return GetBaseMethodInTypeHierarchy (method.DeclaringType, method); + } + + static MethodDefinition GetBaseMethodInTypeHierarchy (TypeDefinition type, MethodDefinition method) + { + TypeReference @base = type.GetInflatedBaseType (); + while (@base != null) { + MethodDefinition base_method = TryMatchMethod (@base, method); + if (base_method != null) + return base_method; + + @base = @base.GetInflatedBaseType (); + } + + return null; + } + + static MethodDefinition GetBaseInflatedInterfaceMethodInTypeHierarchy (Inflater.GenericContext context, TypeDefinition type, MethodDefinition interfaceMethod) + { + TypeReference @base = type.GetInflatedBaseType (); + while (@base != null) { + var candidate = CreateGenericInstanceCandidate (context, @base.Resolve (), interfaceMethod); + + MethodDefinition base_method = TryMatchMethod (@base, candidate); + if (base_method != null) + return base_method; + + @base = @base.GetInflatedBaseType (); + } + + return null; + } + + static IEnumerable GetBaseMethodsInInterfaceHierarchy (MethodDefinition method) + { + return GetBaseMethodsInInterfaceHierarchy (method.DeclaringType, method); + } + + static IEnumerable GetBaseMethodsInInterfaceHierarchy (TypeReference type, MethodDefinition method) + { + foreach (TypeReference @interface in type.GetInflatedInterfaces ()) { + MethodDefinition base_method = TryMatchMethod (@interface, method); + if (base_method != null) + yield return base_method; + + foreach (MethodDefinition @base in GetBaseMethodsInInterfaceHierarchy (@interface, method)) + yield return @base; + } + } + + static MethodDefinition TryMatchMethod (TypeReference type, MethodReference method) + { + foreach (var candidate in type.GetMethods ()) { + if (MethodMatch (candidate, method)) + return candidate.Resolve (); + } + + return null; + } + + static bool MethodMatch (MethodReference candidate, MethodReference method) + { + var candidateDef = candidate.Resolve (); + + if (!candidateDef.IsVirtual) + return false; + + if (candidate.HasParameters != method.HasParameters) + return false; + + if (candidate.Name != method.Name) + return false; + + if (candidate.HasGenericParameters != method.HasGenericParameters) + return false; + + // we need to track what the generic parameter represent - as we cannot allow it to + // differ between the return type or any parameter + if (!TypeMatch (candidate.GetReturnType (), method.GetReturnType ())) + return false; + + if (!candidate.HasParameters) + return true; + + var cp = candidate.Parameters; + var mp = method.Parameters; + if (cp.Count != mp.Count) + return false; + + if (candidate.GenericParameters.Count != method.GenericParameters.Count) + return false; + + for (int i = 0; i < cp.Count; i++) { + if (!TypeMatch (candidate.GetParameterType (i), method.GetParameterType (i))) + return false; + } + + return true; + } + + static bool TypeMatch (IModifierType a, IModifierType b) + { + if (!TypeMatch (a.ModifierType, b.ModifierType)) + return false; + + return TypeMatch (a.ElementType, b.ElementType); + } + + static bool TypeMatch (TypeSpecification a, TypeSpecification b) + { + var gita = a as GenericInstanceType; + if (gita != null) + return TypeMatch (gita, (GenericInstanceType) b); + + var mta = a as IModifierType; + if (mta != null) + return TypeMatch (mta, (IModifierType) b); + + return TypeMatch (a.ElementType, b.ElementType); + } + + static bool TypeMatch (GenericInstanceType a, GenericInstanceType b) + { + if (!TypeMatch (a.ElementType, b.ElementType)) + return false; + + if (a.HasGenericArguments != b.HasGenericArguments) + return false; + + if (!a.HasGenericArguments) + return true; + + var gaa = a.GenericArguments; + var gab = b.GenericArguments; + if (gaa.Count != gab.Count) + return false; + + for (int i = 0; i < gaa.Count; i++) { + if (!TypeMatch (gaa [i], gab [i])) + return false; + } + + return true; + } + + static bool TypeMatch (GenericParameter a, GenericParameter b) + { + if (a.Position != b.Position) + return false; + + if (a.Type != b.Type) + return false; + + return true; + } + + static bool TypeMatch (TypeReference a, TypeReference b) + { + if (a is TypeSpecification || b is TypeSpecification) { + if (a.GetType () != b.GetType ()) + return false; + + return TypeMatch ((TypeSpecification) a, (TypeSpecification) b); + } + + if (a is GenericParameter && b is GenericParameter) + return TypeMatch ((GenericParameter)a, (GenericParameter)b); + + return a.FullName == b.FullName; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs new file mode 100644 index 000000000000..627d8121ea84 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs @@ -0,0 +1,464 @@ +// +// Annotations.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Linker { + + public partial class AnnotationStore { + + protected readonly LinkContext context; + + protected readonly Dictionary assembly_actions = new Dictionary (); + protected readonly Dictionary method_actions = new Dictionary (); + protected readonly Dictionary method_stub_values = new Dictionary (); + protected readonly Dictionary field_values = new Dictionary (); + protected readonly HashSet field_init = new HashSet (); + protected readonly HashSet fieldType_init = new HashSet (); + protected readonly HashSet marked = new HashSet (); + protected readonly HashSet processed = new HashSet (); + protected readonly Dictionary preserved_types = new Dictionary (); + protected readonly Dictionary> preserved_methods = new Dictionary> (); + protected readonly HashSet public_api = new HashSet (); + protected readonly Dictionary> override_methods = new Dictionary> (); + protected readonly Dictionary> base_methods = new Dictionary> (); + protected readonly Dictionary symbol_readers = new Dictionary (); + protected readonly Dictionary> class_type_base_hierarchy = new Dictionary> (); + protected readonly Dictionary> derived_interfaces = new Dictionary>(); + + protected readonly Dictionary> custom_annotations = new Dictionary> (); + protected readonly Dictionary> resources_to_remove = new Dictionary> (); + protected readonly HashSet marked_attributes = new HashSet (); + readonly HashSet marked_types_with_cctor = new HashSet (); + protected readonly HashSet marked_instantiated = new HashSet (); + protected readonly HashSet indirectly_called = new HashSet(); + + + public AnnotationStore (LinkContext context) => this.context = context; + + public bool ProcessSatelliteAssemblies { get; set; } + + protected Tracer Tracer { + get { + return context.Tracer; + } + } + + [Obsolete ("Use Tracer in LinkContext directly")] + public void PrepareDependenciesDump () + { + Tracer.AddRecorder (new XmlDependencyRecorder (context)); + } + + [Obsolete ("Use Tracer in LinkContext directly")] + public void PrepareDependenciesDump (string filename) + { + Tracer.AddRecorder (new XmlDependencyRecorder (context, filename)); + } + + public ICollection GetAssemblies () + { + return assembly_actions.Keys; + } + + public AssemblyAction GetAction (AssemblyDefinition assembly) + { + AssemblyAction action; + if (assembly_actions.TryGetValue (assembly, out action)) + return action; + + throw new InvalidOperationException($"No action for the assembly {assembly.Name} defined"); + } + + public MethodAction GetAction (MethodDefinition method) + { + MethodAction action; + if (method_actions.TryGetValue (method, out action)) + return action; + + return MethodAction.Nothing; + } + + public void SetAction (AssemblyDefinition assembly, AssemblyAction action) + { + assembly_actions [assembly] = action; + } + + public bool HasAction (AssemblyDefinition assembly) + { + return assembly_actions.ContainsKey (assembly); + } + + public void SetAction (MethodDefinition method, MethodAction action) + { + method_actions [method] = action; + } + + public void SetMethodStubValue (MethodDefinition method, object value) + { + method_stub_values [method] = value; + } + + public void SetFieldValue (FieldDefinition field, object value) + { + field_values [field] = value; + } + + public void SetSubstitutedInit (FieldDefinition field) + { + field_init.Add (field); + } + + public bool HasSubstitutedInit (FieldDefinition field) + { + return field_init.Contains (field); + } + + public void SetSubstitutedInit (TypeDefinition type) + { + fieldType_init.Add (type); + } + + public bool HasSubstitutedInit (TypeDefinition type) + { + return fieldType_init.Contains (type); + } + + public void Mark (IMetadataTokenProvider provider) + { + marked.Add (provider); + Tracer.AddDependency (provider, true); + } + + public void Mark (CustomAttribute attribute) + { + marked_attributes.Add (attribute); + } + + public void MarkAndPush (IMetadataTokenProvider provider) + { + Mark (provider); + Tracer.Push (provider, false); + } + + public bool IsMarked (IMetadataTokenProvider provider) + { + return marked.Contains (provider); + } + + public bool IsMarked (CustomAttribute attribute) + { + return marked_attributes.Contains (attribute); + } + + public void MarkIndirectlyCalledMethod (MethodDefinition method) + { + if (!context.AddReflectionAnnotations) + return; + + indirectly_called.Add (method); + } + + public bool HasMarkedAnyIndirectlyCalledMethods () + { + return indirectly_called.Count != 0; + } + + public bool IsIndirectlyCalled (MethodDefinition method) + { + return indirectly_called.Contains (method); + } + + public void MarkInstantiated (TypeDefinition type) + { + marked_instantiated.Add (type); + } + + public bool IsInstantiated (TypeDefinition type) + { + return marked_instantiated.Contains (type); + } + + public void Processed (IMetadataTokenProvider provider) + { + processed.Add (provider); + } + + public bool IsProcessed (IMetadataTokenProvider provider) + { + return processed.Contains (provider); + } + + public bool IsPreserved (TypeDefinition type) + { + return preserved_types.ContainsKey (type); + } + + public void SetPreserve (TypeDefinition type, TypePreserve preserve) + { + TypePreserve existing; + if (preserved_types.TryGetValue (type, out existing)) + preserved_types [type] = ChoosePreserveActionWhichPreservesTheMost (existing, preserve); + else + preserved_types.Add (type, preserve); + } + + public static TypePreserve ChoosePreserveActionWhichPreservesTheMost (TypePreserve leftPreserveAction, TypePreserve rightPreserveAction) + { + if (leftPreserveAction == rightPreserveAction) + return leftPreserveAction; + + if (leftPreserveAction == TypePreserve.All || rightPreserveAction == TypePreserve.All) + return TypePreserve.All; + + if (leftPreserveAction == TypePreserve.Nothing) + return rightPreserveAction; + + if (rightPreserveAction == TypePreserve.Nothing) + return leftPreserveAction; + + if ((leftPreserveAction == TypePreserve.Methods && rightPreserveAction == TypePreserve.Fields) || + (leftPreserveAction == TypePreserve.Fields && rightPreserveAction == TypePreserve.Methods)) + return TypePreserve.All; + + return rightPreserveAction; + } + + public TypePreserve GetPreserve (TypeDefinition type) + { + TypePreserve preserve; + if (preserved_types.TryGetValue (type, out preserve)) + return preserve; + + throw new NotSupportedException ($"No type preserve information for `{type}`"); + } + + public bool TryGetPreserve (TypeDefinition type, out TypePreserve preserve) + { + return preserved_types.TryGetValue (type, out preserve); + } + + public bool TryGetMethodStubValue (MethodDefinition method, out object value) + { + return method_stub_values.TryGetValue (method, out value); + } + + public bool TryGetFieldUserValue (FieldDefinition field, out object value) + { + return field_values.TryGetValue (field, out value); + } + + public HashSet GetResourcesToRemove (AssemblyDefinition assembly) + { + HashSet resources; + if (resources_to_remove.TryGetValue (assembly, out resources)) + return resources; + + return null; + } + + public void AddResourceToRemove (AssemblyDefinition assembly, string name) + { + HashSet resources; + if (!resources_to_remove.TryGetValue (assembly, out resources)) { + resources = resources_to_remove [assembly] = new HashSet (); + } + + resources.Add (name); + } + + public void SetPublic (IMetadataTokenProvider provider) + { + public_api.Add (provider); + } + + public bool IsPublic (IMetadataTokenProvider provider) + { + return public_api.Contains (provider); + } + + public void AddOverride (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) + { + var methods = GetOverrides (@base); + if (methods == null) { + methods = new List (); + override_methods [@base] = methods; + } + + methods.Add (new OverrideInformation (@base, @override, matchingInterfaceImplementation)); + } + + public List GetOverrides (MethodDefinition method) + { + List overrides; + if (override_methods.TryGetValue (method, out overrides)) + return overrides; + + return null; + } + + public void AddBaseMethod (MethodDefinition method, MethodDefinition @base) + { + var methods = GetBaseMethods (method); + if (methods == null) { + methods = new List (); + base_methods [method] = methods; + } + + methods.Add (@base); + } + + public List GetBaseMethods (MethodDefinition method) + { + List bases; + if (base_methods.TryGetValue (method, out bases)) + return bases; + + return null; + } + + public List GetPreservedMethods (TypeDefinition type) + { + return GetPreservedMethods (type as IMemberDefinition); + } + + public void AddPreservedMethod (TypeDefinition type, MethodDefinition method) + { + AddPreservedMethod (type as IMemberDefinition, method); + } + + public List GetPreservedMethods (MethodDefinition method) + { + return GetPreservedMethods (method as IMemberDefinition); + } + + public void AddPreservedMethod (MethodDefinition key, MethodDefinition method) + { + AddPreservedMethod (key as IMemberDefinition, method); + } + + List GetPreservedMethods (IMemberDefinition definition) + { + List preserved; + if (preserved_methods.TryGetValue (definition, out preserved)) + return preserved; + + return null; + } + + void AddPreservedMethod (IMemberDefinition definition, MethodDefinition method) + { + var methods = GetPreservedMethods (definition); + if (methods == null) { + methods = new List (); + preserved_methods [definition] = methods; + } + + methods.Add (method); + } + + public void AddSymbolReader (AssemblyDefinition assembly, ISymbolReader symbolReader) + { + symbol_readers [assembly] = symbolReader; + } + + public void CloseSymbolReader (AssemblyDefinition assembly) + { + ISymbolReader symbolReader; + if (!symbol_readers.TryGetValue (assembly, out symbolReader)) + return; + + symbol_readers.Remove (assembly); + symbolReader.Dispose (); + } + + public Dictionary GetCustomAnnotations (object key) + { + Dictionary slots; + if (custom_annotations.TryGetValue (key, out slots)) + return slots; + + slots = new Dictionary (); + custom_annotations.Add (key, slots); + return slots; + } + + public bool HasPreservedStaticCtor (TypeDefinition type) + { + return marked_types_with_cctor.Contains (type); + } + + public bool SetPreservedStaticCtor (TypeDefinition type) + { + return marked_types_with_cctor.Add (type); + } + + public void SetClassHierarchy (TypeDefinition type, List bases) + { + class_type_base_hierarchy [type] = bases; + } + + public List GetClassHierarchy (TypeDefinition type) + { + if (class_type_base_hierarchy.TryGetValue (type, out List bases)) + return bases; + + return null; + } + + public void AddDerivedInterfaceForInterface (TypeDefinition @base, TypeDefinition derived) + { + if (!@base.IsInterface) + throw new ArgumentException ($"{nameof (@base)} must be an interface"); + + if (!derived.IsInterface) + throw new ArgumentException ($"{nameof (derived)} must be an interface"); + + List derivedInterfaces; + if (!derived_interfaces.TryGetValue (@base, out derivedInterfaces)) + derived_interfaces [@base] = derivedInterfaces = new List (); + + derivedInterfaces.Add(derived); + } + + public List GetDerivedInterfacesForInterface (TypeDefinition @interface) + { + if (!@interface.IsInterface) + throw new ArgumentException ($"{nameof (@interface)} must be an interface"); + + List derivedInterfaces; + if (derived_interfaces.TryGetValue (@interface, out derivedInterfaces)) + return derivedInterfaces; + + return null; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyAction.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyAction.cs new file mode 100644 index 000000000000..341339cd1597 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyAction.cs @@ -0,0 +1,55 @@ +// +// AssemblyAction.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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 Mono.Linker { + + public enum AssemblyAction { + // Ignore the assembly + Skip, + // Copy the existing files, assembly and symbols, into the output destination. E.g. .dll and .mdb + // The linker still analyzes the assemblies (to know what they require) but does not modify them. + Copy, + // Copy the existing files, assembly and symbols, into the output destination if and only if + // anything from the assembly is used. + // The linker still analyzes the assemblies (to know what they require) but does not modify them. + CopyUsed, + // Link the assembly + Link, + // Remove the assembly from the output + Delete, + // Save the assembly/symbols in memory without linking it. + // E.g. useful to remove unneeded assembly references (as done in SweepStep), + // resolving [TypeForwardedTo] attributes (like PCL) to their final location + Save, + // Keep all types, methods, and fields but add System.Runtime.BypassNGenAttribute to unmarked methods. + AddBypassNGen, + // Keep all types, methods, and fields in marked assemblies but add System.Runtime.BypassNGenAttribute to unmarked methods. + // Delete unmarked assemblies. + AddBypassNGenUsed + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs new file mode 100644 index 000000000000..143a7559f1be --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs @@ -0,0 +1,157 @@ +// +// AssemblyResolver.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Collections.Generic; + +namespace Mono.Linker { + +#if FEATURE_ILLINK + public class AssemblyResolver : DirectoryAssemblyResolver { +#else + public class AssemblyResolver : BaseAssemblyResolver { +#endif + + readonly Dictionary _assemblies; + HashSet _unresolvedAssemblies; + bool _ignoreUnresolved; + LinkContext _context; + readonly Collection _references; + + + public IDictionary AssemblyCache { + get { return _assemblies; } + } + + public AssemblyResolver () + : this (new Dictionary (StringComparer.OrdinalIgnoreCase)) + { + } + + public AssemblyResolver (Dictionary assembly_cache) + { + _assemblies = assembly_cache; + _references = new Collection () { }; + } + + public bool IgnoreUnresolved { + get { return _ignoreUnresolved; } + set { _ignoreUnresolved = value; } + } + + public LinkContext Context { + get { return _context; } + set { _context = value; } + } + +#if !FEATURE_ILLINK + // The base class's definition of GetAssembly is visible when using DirectoryAssemblyResolver. + AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) + { + if (parameters.AssemblyResolver == null) + parameters.AssemblyResolver = this; + + return ModuleDefinition.ReadModule (file, parameters).Assembly; + } +#endif + + AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection references, ReaderParameters parameters) + { + var fileName = name.Name + ".dll"; + foreach (var reference in references) { + if (Path.GetFileName (reference) != fileName) + continue; + try { + return GetAssembly (reference, parameters); + } catch (BadImageFormatException) { + continue; + } + } + + return null; + } + + public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) + { + // Validate arguments, similarly to how the base class does it. + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + AssemblyDefinition asm = null; + if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { + try { + // Any full path explicit reference takes precedence over other look up logic + asm = ResolveFromReferences (name, _references, parameters); + + // Fall back to the base class resolution logic + if (asm == null) + asm = base.Resolve (name, parameters); + + _assemblies [name.Name] = asm; + } catch (AssemblyResolutionException) { + if (!_ignoreUnresolved) + throw; + _context.LogMessage ($"warning: Ignoring unresolved assembly '{name.Name}'."); + if (_unresolvedAssemblies == null) + _unresolvedAssemblies = new HashSet (); + _unresolvedAssemblies.Add (name.Name); + } + } + + return asm; + } + + public virtual AssemblyDefinition CacheAssembly (AssemblyDefinition assembly) + { + _assemblies [assembly.Name.Name] = assembly; + base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FileName)); + return assembly; + } + + public void AddReferenceAssembly (string referencePath) + { + _references.Add (referencePath); + } + + protected override void Dispose (bool disposing) + { + foreach (var asm in _assemblies.Values) { + asm.Dispose (); + } + + _assemblies.Clear (); + if (_unresolvedAssemblies != null) + _unresolvedAssemblies.Clear (); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyUtilities.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyUtilities.cs new file mode 100644 index 000000000000..a0da2a92fb7a --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyUtilities.cs @@ -0,0 +1,16 @@ +using System; +using Mono.Cecil; + +namespace Mono.Linker { + + public static class AssemblyUtilities { + + public static bool IsCrossgened (this ModuleDefinition module) + { + return (module.Attributes & ModuleAttributes.ILOnly) == 0 && + (module.Attributes & ModuleAttributes.ILLibrary) != 0; + } + + } + +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs new file mode 100644 index 000000000000..b4f62ce88beb --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs @@ -0,0 +1,87 @@ +using Mono.Cecil; + +namespace Mono.Linker +{ + public static class BCL + { + public static class EventTracingForWindows + { + public static bool IsEventSourceImplementation (TypeDefinition type, LinkContext context = null) + { + if (!type.IsClass) + return false; + + while (type.BaseType != null) { + var bt = type.BaseType.Resolve (); + + if (bt == null) { + if (context != null && !context.IgnoreUnresolved) + throw new ResolutionException (type.BaseType); + + break; + } + + if (IsEventSourceType (bt)) + return true; + + type = bt; + } + + return false; + } + + public static bool IsEventSourceType (TypeReference type) + { + return type.Namespace == "System.Diagnostics.Tracing" && type.Name == "EventSource"; + } + + public static bool IsNonEventAtribute (TypeReference type) + { + return type.Namespace == "System.Diagnostics.Tracing" && type.Name == "NonEventAttribute"; + } + + public static bool IsProviderName (string name) + { + return name == "Keywords" || name == "Tasks" || name == "Opcodes"; + } + } + + public static bool IsIDisposableImplementation (MethodDefinition method) + { + if (method.Name != "Dispose" || method.ReturnType.MetadataType != MetadataType.Void) + return false; + + if (method.HasParameters || method.HasGenericParameters || method.IsStatic) + return false; + + if (!method.IsFinal) + return false; + + return true; + } + + static readonly string[] corlibNames = new [] { + "mscorlib", + "System.Runtime", + "System.Private.CoreLib", + "netstandard" + }; + + public static TypeDefinition FindPredefinedType (string ns, string name, LinkContext context) + { + var cache = context.Resolver.AssemblyCache; + + foreach (var corlibName in corlibNames) { + if (!cache.TryGetValue (corlibName, out AssemblyDefinition corlib)) + continue; + + TypeDefinition type = corlib.MainModule.GetType (ns, name); + // The assembly could be a facade with type forwarders, in which case we don't find the type in this assembly. + if (type != null) + return type; + } + + return null; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs new file mode 100644 index 000000000000..f7059f2b89f2 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs @@ -0,0 +1,11 @@ +using System; +namespace Mono.Linker +{ + public class ConsoleLogger : ILogger + { + public void LogMessage (MessageImportance importance, string message, params object[] values) + { + Console.WriteLine (message, values); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/I18nAssemblies.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/I18nAssemblies.cs new file mode 100644 index 000000000000..a14c58fe2aed --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/I18nAssemblies.cs @@ -0,0 +1,47 @@ +// +// I18nAssemblies.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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; + +namespace Mono.Linker { + + [Flags] + public enum I18nAssemblies { + + None = 0, + + CJK = 1, + MidEast = 2, + Other = 4, + Rare = 8, + West = 16, + + All = CJK | MidEast | Other | Rare | West, + Base + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs new file mode 100644 index 000000000000..de4e4616e943 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs @@ -0,0 +1,44 @@ +// +// IDependencyRecorder.cs +// +// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.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 Mono.Linker +{ + /// + /// Abstraction exposed by the linker (mostly MarkStep, but not only) - it will call this interface + /// every time it finds a dependency between two parts of the dependency graph. + /// + public interface IDependencyRecorder + { + /// + /// Reports a dependency detected by the linker. + /// + /// The source of the dependency (for example the caller method). + /// The target of the dependency (for example the callee method). + /// true if the target is also marked by the MarkStep. + /// The source and target are typically Cecil metadata objects (MethodDefinition, TypeDefinition, ...) + /// but they can also be the linker steps or really any other object. + void RecordDependency (object source, object target, bool marked); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs new file mode 100644 index 000000000000..d4f610fbb533 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs @@ -0,0 +1,15 @@ +using System; +namespace Mono.Linker +{ + public enum MessageImportance + { + High, + Low, + Normal, + } + + public interface ILogger + { + void LogMessage (MessageImportance importance, string message, params object[] values); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs new file mode 100644 index 000000000000..b3aae2b2ea78 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs @@ -0,0 +1,62 @@ +// +// IReflectionPatternRecorder.cs +// +// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.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 Mono.Cecil; + +namespace Mono.Linker +{ + /// + /// Interface which is called every time the linker inspects a pattern of code involving reflection to determine a more complex + /// dependency. + /// + /// + /// The rules are such that if a given callsite of a "reflectionMethod" gets examined + /// linker will always report it one way or another: + /// - it will either call RecognizedReflectionAccessPattern method when it can figure out exactly the dependency. + /// - or it will call UnrecognizedReflectionAccessPattern with an optional message describing why it could not recognize + /// the pattern. + /// + public interface IReflectionPatternRecorder + { + /// + /// Called when the linker recognized a reflection access pattern (and thus was able to correctly apply marking to the accessed item). + /// + /// The method which contains the reflection access pattern. + /// The reflection method which is at the heart of the access pattern. + /// The item accessed through reflection. This can be one of: + /// TypeDefinition, MethodDefinition, PropertyDefinition, FieldDefinition, EventDefinition. + void RecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, IMemberDefinition accessedItem); + + /// + /// Called when the linker detected a reflection access but was not able to recognize the entire pattern. + /// + /// The method which contains the reflection access code. + /// The reflection method which is at the heart of the access code. + /// Humanly readable message describing what failed during the pattern recognition. + /// This effectively means that there's a potential hole in the linker marking - some items which are accessed only through + /// reflection may not be marked correctly and thus may fail at runtime. + void UnrecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, string message); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IXApiVisitor.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IXApiVisitor.cs new file mode 100644 index 000000000000..204d699ee14e --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IXApiVisitor.cs @@ -0,0 +1,47 @@ +// +// XApiVisitor.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Xml.XPath; + +using Mono.Cecil; + +namespace Mono.Linker { + + public interface IXApiVisitor { + + void OnAssembly (XPathNavigator nav, AssemblyDefinition assembly); + void OnAttribute (XPathNavigator nav); + void OnClass (XPathNavigator nav, TypeDefinition type); + void OnInterface (XPathNavigator nav, TypeDefinition type); + void OnField (XPathNavigator nav, FieldDefinition field); + void OnMethod (XPathNavigator nav, MethodDefinition method); + void OnConstructor (XPathNavigator nav, MethodDefinition method); + void OnProperty (XPathNavigator nav, PropertyDefinition property); + void OnEvent (XPathNavigator nav, EventDefinition evt); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs new file mode 100644 index 000000000000..65c09f60fa1d --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mono.Cecil; + +namespace Mono.Linker { + class Inflater { + public static TypeReference InflateType(GenericContext context, TypeReference typeReference) + { + var typeDefinition = InflateTypeWithoutException(context, typeReference); + if (typeDefinition == null) + throw new InvalidOperationException($"Unable to resolve a reference to the type '{typeReference.FullName}' in the assembly '{typeReference.Module.Assembly.FullName}'. Does this type exist in a different assembly in the project?"); + + return typeDefinition; + } + + public static GenericInstanceType InflateType(GenericContext context, TypeDefinition typeDefinition) + { + return ConstructGenericType(context, typeDefinition, typeDefinition.GenericParameters); + } + + public static GenericInstanceType InflateType(GenericContext context, GenericInstanceType genericInstanceType) + { + var inflatedType = ConstructGenericType(context, genericInstanceType.Resolve(), genericInstanceType.GenericArguments); + inflatedType.MetadataToken = genericInstanceType.MetadataToken; + return inflatedType; + } + + public static TypeReference InflateTypeWithoutException(GenericContext context, TypeReference typeReference) + { + var genericParameter = typeReference as GenericParameter; + if (genericParameter != null) + { + if (context.Method == null && genericParameter.Type != GenericParameterType.Type) + { + // If no method is specified assume only partial inflation is desired. + return typeReference; + } + + var genericArgumentType = genericParameter.Type == GenericParameterType.Type + ? context.Type.GenericArguments[genericParameter.Position] + : context.Method.GenericArguments[genericParameter.Position]; + + var inflatedType = genericArgumentType; + return inflatedType; + } + var genericInstanceType = typeReference as GenericInstanceType; + if (genericInstanceType != null) + return InflateType(context, genericInstanceType); + + var arrayType = typeReference as ArrayType; + if (arrayType != null) + return new ArrayType(InflateType(context, arrayType.ElementType), arrayType.Rank); + + var byReferenceType = typeReference as ByReferenceType; + if (byReferenceType != null) + return new ByReferenceType(InflateType(context, byReferenceType.ElementType)); + + var pointerType = typeReference as PointerType; + if (pointerType != null) + return new PointerType(InflateType(context, pointerType.ElementType)); + + var reqModType = typeReference as RequiredModifierType; + if (reqModType != null) + return InflateTypeWithoutException(context, reqModType.ElementType); + + var optModType = typeReference as OptionalModifierType; + if (optModType != null) + return InflateTypeWithoutException(context, optModType.ElementType); + + return typeReference.Resolve(); + } + + static GenericInstanceType ConstructGenericType(GenericContext context, TypeDefinition typeDefinition, IEnumerable genericArguments) + { + var inflatedType = new GenericInstanceType(typeDefinition); + + foreach (var genericArgument in genericArguments) + inflatedType.GenericArguments.Add(InflateType(context, genericArgument)); + + return inflatedType; + } + + public class GenericContext + { + private readonly GenericInstanceType _type; + private readonly GenericInstanceMethod _method; + + public GenericContext(GenericInstanceType type, GenericInstanceMethod method) + { + _type = type; + _method = method; + } + + public GenericInstanceType Type + { + get { return _type; } + } + + public GenericInstanceMethod Method + { + get { return _method; } + } + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs new file mode 100644 index 000000000000..02dcf6469ad4 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs @@ -0,0 +1,31 @@ +using Mono.Cecil; + +namespace Mono.Linker +{ + public class KnownMembers + { + public MethodDefinition NotSupportedExceptionCtorString { get; set; } + public MethodDefinition DisablePrivateReflectionAttributeCtor { get; set; } + public MethodDefinition ObjectCtor { get; set; } + + public static bool IsNotSupportedExceptionCtorString (MethodDefinition method) + { + if (!method.IsConstructor || method.IsStatic || !method.HasParameters) + return false; + + if (method.Parameters.Count != 1 || method.Parameters [0].ParameterType.MetadataType != MetadataType.String) + return false; + + return true; + } + + public static bool IsSatelliteAssemblyMarker (MethodDefinition method) + { + if (!method.IsConstructor || method.IsStatic) + return false; + + var declaringType = method.DeclaringType; + return declaringType.Name == "ResourceManager" && declaringType.Namespace == "System.Resources"; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs new file mode 100644 index 000000000000..8d596844f727 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs @@ -0,0 +1,467 @@ +// +// LinkContext.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Linker { + + public class UnintializedContextFactory { + virtual public AnnotationStore CreateAnnotationStore (LinkContext context) => new AnnotationStore (context); + virtual public MarkingHelpers CreateMarkingHelpers (LinkContext context) => new MarkingHelpers (context); + virtual public Tracer CreateTracer (LinkContext context) => new Tracer (context); + } + + public class LinkContext : IDisposable { + + Pipeline _pipeline; + AssemblyAction _coreAction; + AssemblyAction _userAction; + Dictionary _actions; + string _outputDirectory; + readonly Dictionary _parameters; + bool _linkSymbols; + bool _keepTypeForwarderOnlyAssemblies; + bool _keepMembersForDebugger; + bool _ignoreUnresolved; + + AssemblyResolver _resolver; + + ReaderParameters _readerParameters; + ISymbolReaderProvider _symbolReaderProvider; + ISymbolWriterProvider _symbolWriterProvider; + + AnnotationStore _annotations; + + public Pipeline Pipeline { + get { return _pipeline; } + } + + public AnnotationStore Annotations { + get { return _annotations; } + } + + public bool DeterministicOutput { get; set; } + + public string OutputDirectory { + get { return _outputDirectory; } + set { _outputDirectory = value; } + } + + public AssemblyAction CoreAction { + get { return _coreAction; } + set { _coreAction = value; } + } + + public AssemblyAction UserAction { + get { return _userAction; } + set { _userAction = value; } + } + + public bool LinkSymbols { + get { return _linkSymbols; } + set { _linkSymbols = value; } + } + + public bool KeepTypeForwarderOnlyAssemblies + { + get { return _keepTypeForwarderOnlyAssemblies; } + set { _keepTypeForwarderOnlyAssemblies = value; } + } + + public bool KeepMembersForDebugger + { + get { return _keepMembersForDebugger; } + set { _keepMembersForDebugger = value; } + } + + public bool IgnoreUnresolved + { + get { return _ignoreUnresolved; } + set { _ignoreUnresolved = value; } + } + + public bool EnableReducedTracing { get; set; } + + public bool KeepUsedAttributeTypesOnly { get; set; } + + public bool KeepDependencyAttributes { get; set; } + + public bool StripResources { get; set; } + + public List Substitutions { get; private set; } + + public System.Collections.IDictionary Actions { + get { return _actions; } + } + + public AssemblyResolver Resolver { + get { return _resolver; } + } + + public ReaderParameters ReaderParameters { + get { return _readerParameters; } + } + + public ISymbolReaderProvider SymbolReaderProvider { + get { return _symbolReaderProvider; } + set { _symbolReaderProvider = value; } + } + + public ISymbolWriterProvider SymbolWriterProvider { + get { return _symbolWriterProvider; } + set { _symbolWriterProvider = value; } + } + + public bool LogMessages { get; set; } + + public ILogger Logger { private get; set; } = new ConsoleLogger (); + + public MarkingHelpers MarkingHelpers { get; private set; } + + public KnownMembers MarkedKnownMembers { get; private set; } + + public Tracer Tracer { get; private set; } + + public IReflectionPatternRecorder ReflectionPatternRecorder { get; set; } + + public string [] ExcludedFeatures { get; set; } + + public CodeOptimizations DisabledOptimizations { get; set; } + + public bool AddReflectionAnnotations { get; set; } + + public string AssemblyListFile { get; set; } + + public LinkContext (Pipeline pipeline) + : this (pipeline, new AssemblyResolver ()) + { + } + + public LinkContext (Pipeline pipeline, AssemblyResolver resolver) + : this(pipeline, resolver, new ReaderParameters + { + AssemblyResolver = resolver + }, new UnintializedContextFactory ()) + { + } + + public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParameters readerParameters, UnintializedContextFactory factory) + { + _pipeline = pipeline; + _resolver = resolver; + _resolver.Context = this; + _actions = new Dictionary (); + _parameters = new Dictionary (); + _readerParameters = readerParameters; + + SymbolReaderProvider = new DefaultSymbolReaderProvider (false); + + if (factory == null) + throw new ArgumentNullException (nameof (factory)); + + _annotations = factory.CreateAnnotationStore (this); + MarkingHelpers = factory.CreateMarkingHelpers (this); + Tracer = factory.CreateTracer (this); + ReflectionPatternRecorder = new LoggingReflectionPatternRecorder (this); + MarkedKnownMembers = new KnownMembers (); + StripResources = true; + + // See https://github.com/mono/linker/issues/612 + DisabledOptimizations |= CodeOptimizations.UnreachableBodies; + DisabledOptimizations |= CodeOptimizations.ClearInitLocals; + DisabledOptimizations |= CodeOptimizations.IPConstantPropagation; + } + + public void AddSubstitutionFile (string file) + { + if (Substitutions == null) { + Substitutions = new List (); + Substitutions.Add (file); + return; + } + + if (Substitutions.Contains (file)) + return; + + Substitutions.Add (file); + } + + public TypeDefinition GetType (string fullName) + { + int pos = fullName.IndexOf (","); + fullName = TypeReferenceExtensions.ToCecilName (fullName); + if (pos == -1) { + foreach (AssemblyDefinition asm in GetAssemblies ()) { + var type = asm.MainModule.GetType (fullName); + if (type != null) + return type; + } + + return null; + } + + string asmname = fullName.Substring (pos + 1); + fullName = fullName.Substring (0, pos); + AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname)); + return assembly.MainModule.GetType (fullName); + } + + public AssemblyDefinition Resolve (string name) + { + if (File.Exists (name)) { + try { + AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters); + return _resolver.CacheAssembly (assembly); + } catch (Exception e) { + throw new AssemblyResolutionException (new AssemblyNameReference (name, new Version ()), e); + } + } + + return Resolve (new AssemblyNameReference (name, new Version ())); + } + + public AssemblyDefinition Resolve (IMetadataScope scope) + { + AssemblyNameReference reference = GetReference (scope); + try { + AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters); + + if (assembly != null) + RegisterAssembly (assembly); + + return assembly; + } + catch (Exception e) { + throw new AssemblyResolutionException (reference, e); + } + } + + public void RegisterAssembly (AssemblyDefinition assembly) + { + if (SeenFirstTime (assembly)) { + SafeReadSymbols (assembly); + SetDefaultAction (assembly); + } + } + + protected bool SeenFirstTime (AssemblyDefinition assembly) + { + return !_annotations.HasAction (assembly); + } + + public virtual void SafeReadSymbols (AssemblyDefinition assembly) + { + if (assembly.MainModule.HasSymbols) + return; + + if (_symbolReaderProvider == null) + throw new ArgumentNullException (nameof (_symbolReaderProvider)); + + try { + var symbolReader = _symbolReaderProvider.GetSymbolReader ( + assembly.MainModule, + assembly.MainModule.FileName); + + if (symbolReader == null) + return; + + try { + assembly.MainModule.ReadSymbols (symbolReader); + } catch { + symbolReader.Dispose (); + return; + } + + // Add symbol reader to annotations only if we have successfully read it + _annotations.AddSymbolReader (assembly, symbolReader); + } catch { } + } + + public virtual ICollection ResolveReferences (AssemblyDefinition assembly) + { + List references = new List (); + if (assembly == null) + return references; + foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) { + AssemblyDefinition definition = Resolve (reference); + if (definition != null) + references.Add (definition); + } + return references; + } + + static AssemblyNameReference GetReference (IMetadataScope scope) + { + AssemblyNameReference reference; + if (scope is ModuleDefinition) { + AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly; + reference = asm.Name; + } else + reference = (AssemblyNameReference) scope; + + return reference; + } + + public void SetAction (AssemblyDefinition assembly, AssemblyAction defaultAction) + { + RegisterAssembly (assembly); + + if (!_actions.TryGetValue (assembly.Name.Name, out AssemblyAction action)) + action = defaultAction; + + Annotations.SetAction (assembly, action); + } + + protected void SetDefaultAction (AssemblyDefinition assembly) + { + AssemblyAction action; + + AssemblyNameDefinition name = assembly.Name; + + if (_actions.TryGetValue (name.Name, out action)) { + } else if (IsCore (name)) { + action = _coreAction; + } else { + action = _userAction; + } + + _annotations.SetAction (assembly, action); + } + + public static bool IsCore (AssemblyNameReference name) + { + switch (name.Name) { + case "mscorlib": + case "Accessibility": + case "Mono.Security": + // WPF + case "PresentationFramework": + case "PresentationCore": + case "WindowsBase": + case "UIAutomationProvider": + case "UIAutomationTypes": + case "PresentationUI": + case "ReachFramework": + case "netstandard": + return true; + default: + return name.Name.StartsWith ("System") + || name.Name.StartsWith ("Microsoft"); + } + } + + public virtual AssemblyDefinition [] GetAssemblies () + { + var cache = _resolver.AssemblyCache; + AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count]; + cache.Values.CopyTo (asms, 0); + return asms; + } + + public void SetParameter (string key, string value) + { + _parameters [key] = value; + } + + public bool HasParameter (string key) + { + return _parameters.ContainsKey (key); + } + + public string GetParameter (string key) + { + string val = null; + _parameters.TryGetValue (key, out val); + return val; + } + + public void Dispose () + { + _resolver.Dispose (); + } + + public bool IsFeatureExcluded (string featureName) + { + return ExcludedFeatures != null && Array.IndexOf (ExcludedFeatures, featureName) >= 0; + } + + public bool IsOptimizationEnabled (CodeOptimizations optimization) + { + return (DisabledOptimizations & optimization) == 0; + } + + public void LogMessage (string message) + { + LogMessage (MessageImportance.Normal, message); + } + + public void LogMessage (MessageImportance importance, string message) + { + if (LogMessages && Logger != null) + Logger.LogMessage (importance, "{0}", message); + } + } + + [Flags] + public enum CodeOptimizations + { + BeforeFieldInit = 1 << 0, + + /// + /// Option to disable removal of overrides of virtual methods when a type is never instantiated + /// + /// Being able to disable this optimization is helpful when trying to troubleshoot problems caused by types created via reflection or from native + /// that do not get an instance constructor marked. + /// + OverrideRemoval = 1 << 1, + + /// + /// Option to disable delaying marking of instance methods until an instance of that type could exist + /// + UnreachableBodies = 1 << 2, + + /// + /// Option to clear the initlocals flag on methods + /// + ClearInitLocals = 1 << 3, + + /// + /// Option to remove .interfaceimpl for interface types that are not used + /// + UnusedInterfaces = 1 << 4, + + /// + /// Option to do interprocedural constant propagation on return values + /// + IPConstantPropagation = 1 << 5 + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs new file mode 100644 index 000000000000..c4ca8f67e1d5 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs @@ -0,0 +1,17 @@ +using System; + +namespace Mono.Linker +{ + public class LoadException : Exception + { + public LoadException (string message) + : base (message) + { + } + + public LoadException (string message, Exception innerException) + : base (message, innerException) + { + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs new file mode 100644 index 000000000000..f9c0d89e938d --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs @@ -0,0 +1,49 @@ +// +// LoggingReflectionPatternRecorder.cs +// +// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.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 Mono.Cecil; + +namespace Mono.Linker +{ + class LoggingReflectionPatternRecorder : IReflectionPatternRecorder + { + private readonly LinkContext _context; + + public LoggingReflectionPatternRecorder (LinkContext context) + { + _context = context; + } + + public void RecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, IMemberDefinition accessedItem) + { + // Do nothing - there's no logging for successfully recognized patterns + } + + public void UnrecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, string message) + { + _context.LogMessage (MessageImportance.Low, message); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs new file mode 100644 index 000000000000..fd8d6057c346 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs @@ -0,0 +1,27 @@ +using System; + +using Mono.Cecil; + +namespace Mono.Linker +{ + public class MarkException : Exception + { + public MethodDefinition Method { get; private set; } + + public MarkException (string message) + : base (message) + { + } + + public MarkException (string message, Exception innerException) + : base (message, innerException) + { + } + + public MarkException (string message, Exception innerException, MethodDefinition method) + : base (message, innerException) + { + Method = method; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs new file mode 100644 index 000000000000..b477a5ce3896 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs @@ -0,0 +1,20 @@ +using System; +using Mono.Cecil; + +namespace Mono.Linker { + public class MarkingHelpers { + protected readonly LinkContext _context; + + public MarkingHelpers (LinkContext context) + { + _context = context; + } + + public void MarkExportedType (ExportedType type, ModuleDefinition module) + { + _context.Annotations.Mark (type); + if (_context.KeepTypeForwarderOnlyAssemblies) + _context.Annotations.Mark (module); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodAction.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodAction.cs new file mode 100644 index 000000000000..a3550e78396b --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodAction.cs @@ -0,0 +1,38 @@ +// +// MethodAction.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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 Mono.Linker { + + public enum MethodAction { + Nothing, + Parse, + ForceParse, + ConvertToStub, + ConvertToThrow, + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs new file mode 100644 index 000000000000..267a7c3ba6d2 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Linker { + public static class MethodBodyScanner { + public static bool IsWorthConvertingToThrow (MethodBody body) + { + // Some bodies are cheaper size wise to leave alone than to convert to a throw + Instruction previousMeaningful = null; + int meaningfulCount = 0; + foreach (var ins in body.Instructions) { + // Handle ignoring noops because because (1) it's a valid case to ignore + // and (2) When running the tests on .net core roslyn tosses in no ops + // and that leads to a difference in test results between mcs and .net framework csc. + if (ins.OpCode.Code == Code.Nop) + continue; + + meaningfulCount++; + + if (meaningfulCount == 1 && ins.OpCode.Code == Code.Ret) + return false; + + if (meaningfulCount == 2 && ins.OpCode.Code == Code.Ret && previousMeaningful != null) { + if (previousMeaningful.OpCode.StackBehaviourPop == StackBehaviour.Pop0) { + switch (previousMeaningful.OpCode.StackBehaviourPush) { + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + return false; + } + + switch (previousMeaningful.OpCode.Code) { + case Code.Ldnull: + return false; + } + } + } + + if (meaningfulCount >= 2) + return true; + + previousMeaningful = ins; + } + + return true; + } + + public static IEnumerable GetReferencedInterfaces (AnnotationStore annotations, MethodBody body) + { + var possibleStackTypes = AllPossibleStackTypes (body.Method); + if (possibleStackTypes.Count == 0) + return null; + + var interfaceTypes = possibleStackTypes.Where (t => t.IsInterface).ToArray (); + if (interfaceTypes.Length == 0) + return null; + + var interfaceImplementations = new HashSet (); + + // If a type could be on the stack in the body and an interface it implements could be on the stack on the body + // then we need to mark that interface implementation. When this occurs it is not safe to remove the interface implementation from the type + // even if the type is never instantiated + foreach (var type in possibleStackTypes) { + // We only sweep interfaces on classes so that's why we only care about classes + if (!type.IsClass) + continue; + + AddMatchingInterfaces (interfaceImplementations, type, interfaceTypes); + var bases = annotations.GetClassHierarchy (type); + foreach (var @base in bases) { + AddMatchingInterfaces (interfaceImplementations, @base, interfaceTypes); + } + } + + return interfaceImplementations; + } + + static HashSet AllPossibleStackTypes (MethodDefinition method) + { + if (!method.HasBody) + throw new ArgumentException(); + + var body = method.Body; + var types = new HashSet (); + + foreach (VariableDefinition var in body.Variables) + AddIfResolved (types, var.VariableType); + + foreach(var parameter in body.Method.Parameters) + AddIfResolved (types, parameter.ParameterType); + + foreach (ExceptionHandler eh in body.ExceptionHandlers) { + if (eh.HandlerType == ExceptionHandlerType.Catch) { + AddIfResolved (types, eh.CatchType); + } + } + + foreach (Instruction instruction in body.Instructions) { + if (instruction.Operand is FieldReference fieldReference) { + AddIfResolved (types, fieldReference.Resolve ()?.FieldType); + } else if (instruction.Operand is MethodReference methodReference) { + if (methodReference is GenericInstanceMethod genericInstanceMethod) + AddFromGenericInstance (types, genericInstanceMethod); + + if (methodReference.DeclaringType is GenericInstanceType genericInstanceType) + AddFromGenericInstance (types, genericInstanceType); + + var resolvedMethod = methodReference.Resolve (); + if (resolvedMethod != null) { + if (resolvedMethod.HasParameters) { + foreach (var param in resolvedMethod.Parameters) + AddIfResolved (types, param.ParameterType); + } + + AddFromGenericParameterProvider (types, resolvedMethod); + AddFromGenericParameterProvider (types, resolvedMethod.DeclaringType); + AddIfResolved (types, resolvedMethod.ReturnType); + } + } + } + + return types; + } + + static void AddMatchingInterfaces (HashSet results, TypeDefinition type, TypeDefinition [] interfaceTypes) + { + foreach (var interfaceType in interfaceTypes) { + if (type.HasInterface (interfaceType, out InterfaceImplementation implementation)) + results.Add (implementation); + } + } + + static void AddFromGenericInstance (HashSet set, IGenericInstance instance) + { + if (!instance.HasGenericArguments) + return; + + foreach (var genericArgument in instance.GenericArguments) + AddIfResolved (set, genericArgument); + } + + static void AddFromGenericParameterProvider (HashSet set, IGenericParameterProvider provider) + { + if (!provider.HasGenericParameters) + return; + + foreach (var genericParameter in provider.GenericParameters) { + foreach (var constraint in genericParameter.Constraints) + AddIfResolved (set, constraint.ConstraintType); + } + } + + static void AddIfResolved (HashSet set, TypeReference item) + { + var resolved = item?.Resolve (); + if (resolved == null) + return; + set.Add (resolved); + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs new file mode 100644 index 000000000000..b2b066727808 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs @@ -0,0 +1,97 @@ +using Mono.Cecil; + +namespace Mono.Linker +{ + public static class MethodDefinitionExtensions + { + public static bool IsDefaultConstructor (this MethodDefinition method) + { + return IsInstanceConstructor (method) && !method.HasParameters; + } + + public static bool IsInstanceConstructor (this MethodDefinition method) + { + return method.IsConstructor && !method.IsStatic; + } + + public static bool IsIntrinsic (this MethodDefinition method) + { + if (!method.HasCustomAttributes) + return false; + + foreach (var ca in method.CustomAttributes) { + var caType = ca.AttributeType; + if (caType.Name == "IntrinsicAttribute" && caType.Namespace == "System.Runtime.CompilerServices") + return true; + } + + return false; + } + + public static bool IsPropertyMethod (this MethodDefinition md) + { + return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 || + (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0; + } + + public static bool IsPublicInstancePropertyMethod (this MethodDefinition md) + { + return md.IsPublic && !md.IsStatic && IsPropertyMethod (md); + } + + public static bool IsEventMethod (this MethodDefinition md) + { + return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 || + (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 || + (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0; + } + + public static PropertyDefinition GetProperty (this MethodDefinition md) + { + TypeDefinition declaringType = md.DeclaringType; + foreach (PropertyDefinition prop in declaringType.Properties) + if (prop.GetMethod == md || prop.SetMethod == md) + return prop; + + return null; + } + + public static EventDefinition GetEvent (this MethodDefinition md) + { + TypeDefinition declaringType = md.DeclaringType; + foreach (EventDefinition evt in declaringType.Events) + if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md) + return evt; + + return null; + } + + public static bool IsStaticConstructor (this MethodDefinition method) + { + return method.IsConstructor && method.IsStatic; + } + + public static bool IsFinalizer (this MethodDefinition method) + { + if (method.Name != "Finalize" || method.ReturnType.MetadataType != MetadataType.Void) + return false; + + if (method.HasParameters || method.HasGenericParameters || method.IsStatic) + return false; + + return true; + } + + public static void ClearDebugInformation (this MethodDefinition method) + { + // TODO: This always allocates, update when Cecil catches up + var di = method.DebugInformation; + di.SequencePoints.Clear (); + if (di.Scope != null) { + di.Scope.Variables.Clear (); + di.Scope.Constants.Clear (); + di.Scope = null; + } + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs new file mode 100644 index 000000000000..23558db44dcf --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs @@ -0,0 +1,28 @@ +using System; +using Mono.Cecil; + +namespace Mono.Linker +{ + public static class MethodReferenceExtensions + { + public static TypeReference GetReturnType (this MethodReference method) + { + var genericInstance = method.DeclaringType as GenericInstanceType; + + if (genericInstance != null) + return TypeReferenceExtensions.InflateGenericType (genericInstance, method.ReturnType); + + return method.ReturnType; + } + + public static TypeReference GetParameterType (this MethodReference method, int parameterIndex) + { + var genericInstance = method.DeclaringType as GenericInstanceType; + + if (genericInstance != null) + return TypeReferenceExtensions.InflateGenericType (genericInstance, method.Parameters [parameterIndex].ParameterType); + + return method.Parameters [parameterIndex].ParameterType; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs new file mode 100644 index 000000000000..a406625fa315 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs @@ -0,0 +1,17 @@ +using System; + +namespace Mono.Linker +{ + public class OutputException : Exception + { + public OutputException (string message) + : base (message) + { + } + + public OutputException (string message, Exception innerException) + : base (message, innerException) + { + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs new file mode 100644 index 000000000000..f73d8bc1c63c --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using Mono.Cecil; + +namespace Mono.Linker { + [DebuggerDisplay ("{Override}")] + public class OverrideInformation { + public readonly MethodDefinition Base; + public readonly MethodDefinition Override; + public readonly InterfaceImplementation MatchingInterfaceImplementation; + + public OverrideInformation (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) + { + Base = @base; + Override = @override; + MatchingInterfaceImplementation = matchingInterfaceImplementation; + } + + public bool IsOverrideOfInterfaceMember + { + get + { + if (MatchingInterfaceImplementation != null) + return true; + + return Base.DeclaringType.IsInterface; + } + } + + public TypeDefinition InterfaceType + { + get + { + if (!IsOverrideOfInterfaceMember) + return null; + + if (MatchingInterfaceImplementation != null) + return MatchingInterfaceImplementation.InterfaceType.Resolve (); + + return Base.DeclaringType; + } + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs new file mode 100644 index 000000000000..a28de3ba1b24 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs @@ -0,0 +1,152 @@ +// +// Pipeline.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2006 Jb Evain +// +// 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.Collections.Generic; + +using Mono.Linker.Steps; + +namespace Mono.Linker { + + public class Pipeline { + + readonly List _steps; + + public Pipeline () + { + _steps = new List(); + } + + public void PrependStep (IStep step) + { + _steps.Insert (0, step); + } + + public void AppendStep (IStep step) + { + _steps.Add (step); + } + + public void AddStepBefore (Type target, IStep step) + { + for (int i = 0; i < _steps.Count; i++) { + if (target.IsInstanceOfType (_steps [i])) { + _steps.Insert (i, step); + return; + } + } + string msg = String.Format ("Step {0} could not be inserted before (not found) {1}", step, target); + throw new InvalidOperationException (msg); + } + + public void AddStepBefore (IStep target, IStep step) + { + for (int i = 0; i < _steps.Count; i++) { + if (_steps [i] == target) { + _steps.Insert (i, step); + return; + } + } + } + + public void ReplaceStep (Type target, IStep step) + { + AddStepBefore (target, step); + RemoveStep (target); + } + + public void AddStepAfter (Type target, IStep step) + { + for (int i = 0; i < _steps.Count; i++) { + if (target.IsInstanceOfType (_steps [i])) { + if (i == _steps.Count - 1) + _steps.Add (step); + else + _steps.Insert (i + 1, step); + return; + } + } + string msg = String.Format ("Step {0} could not be inserted after (not found) {1}", step, target); + throw new InvalidOperationException (msg); + } + + public void AddStepAfter (IStep target, IStep step) + { + for (int i = 0; i < _steps.Count; i++) { + if (_steps [i] == target) { + if (i == _steps.Count - 1) + _steps.Add (step); + else + _steps.Insert (i + 1, step); + return; + } + } + } + + public void RemoveStep (Type target) + { + for (int i = 0; i < _steps.Count; i++) { + if (_steps [i].GetType () != target) + continue; + + _steps.RemoveAt (i); + break; + } + } + + public void Process (LinkContext context) + { + while (_steps.Count > 0) { + IStep step = _steps [0]; + ProcessStep (context, step); + _steps.Remove (step); + } + } + + protected virtual void ProcessStep (LinkContext context, IStep step) + { + context.Tracer.Push (step); + step.Process (context); + context.Tracer.Pop (); + } + + public IStep [] GetSteps () + { + return _steps.ToArray (); + } + + public bool ContainsStep (Type type) + { + foreach (IStep step in _steps) + if (step.GetType () == type) + return true; + + return false; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs new file mode 100644 index 000000000000..1a6b7109fe93 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs @@ -0,0 +1,115 @@ +// +// Tracer.cs +// +// Author: +// Radek Doulik +// +// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.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.Collections.Generic; + +namespace Mono.Linker +{ + public class Tracer + { + protected readonly LinkContext context; + + Stack dependency_stack; + List recorders; + + public Tracer (LinkContext context) + { + this.context = context; + dependency_stack = new Stack (); + } + + public void Finish () + { + dependency_stack = null; + if (recorders != null) { + foreach (var recorder in recorders) { + if (recorder is IDisposable disposableRecorder) + disposableRecorder.Dispose (); + } + } + + recorders = null; + } + + public void AddRecorder (IDependencyRecorder recorder) + { + if (recorders == null) { + recorders = new List (); + } + + recorders.Add (recorder); + } + + public void Push (object o, bool addDependency = true) + { + if (!IsRecordingEnabled ()) + return; + + if (addDependency && dependency_stack.Count > 0) + AddDependency (o); + + dependency_stack.Push (o); + } + + public void Pop () + { + if (!IsRecordingEnabled ()) + return; + + dependency_stack.Pop (); + } + + bool IsRecordingEnabled () + { + return recorders != null; + } + + public void AddDirectDependency (object b, object e) + { + ReportDependency (b, e, false); + } + + public void AddDependency (object o, bool marked = false) + { + if (!IsRecordingEnabled ()) + return; + + ReportDependency (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o, marked); + } + + private void ReportDependency (object source, object target, bool marked) + { + if (IsRecordingEnabled ()) { + foreach (IDependencyRecorder recorder in recorders) { + recorder.RecordDependency (source, target, marked); + } + } + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs new file mode 100644 index 000000000000..1e06def6eb68 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs @@ -0,0 +1,44 @@ + +using System; +using Mono.Cecil; + +namespace Mono.Linker { + public static class TypeDefinitionExtensions { + public static bool HasInterface (this TypeDefinition type, TypeDefinition interfaceType, out InterfaceImplementation implementation) + { + implementation = null; + if (!type.HasInterfaces) + return false; + + foreach (var iface in type.Interfaces) { + if (iface.InterfaceType.Resolve () == interfaceType) { + implementation = iface; + return true; + } + } + + return false; + } + + public static TypeReference GetEnumUnderlyingType (this TypeDefinition enumType) + { + foreach (var field in enumType.Fields) { + if (!field.IsStatic && field.Name == "value__") { + return field.FieldType; + } + } + + throw new MissingFieldException ($"Enum type '{enumType.FullName}' is missing 'value__' field"); + } + + public static bool IsMulticastDelegate (this TypeDefinition td) + { + return td.BaseType?.Name == "MulticastDelegate" && td.BaseType.Namespace == "System"; + } + + public static bool IsSerializable (this TypeDefinition td) + { + return (td.Attributes & TypeAttributes.Serializable) != 0; + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs new file mode 100644 index 000000000000..15d53c09c6a1 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs @@ -0,0 +1,48 @@ +using System; + +namespace Mono.Linker { + public static class TypeNameParser { + public static bool TryParseTypeAssemblyQualifiedName (string value, out string typeName, out string assemblyName) { + if (string.IsNullOrEmpty (value)) { + typeName = null; + assemblyName = null; + return false; + } + + //Filter the assembly qualified name down to the basic type by removing pointer, reference, and array markers on the type + //We must also convert nested types from + to / to match cecil's formatting + value = value + .Replace ('+', '/') + .Replace ("*", string.Empty) + .Replace ("&", string.Empty); + + while (value.IndexOf ('[') > 0) { + var openidx = value.IndexOf ('['); + var closeidx = value.IndexOf (']'); + + // No matching close ] or out of order + if (closeidx < 0 || closeidx < openidx) { + typeName = null; + assemblyName = null; + return false; + } + + value = value.Remove (openidx, closeidx + 1 - openidx); + } + + var tokens = value.Split (','); + typeName = tokens [0].Trim (); + assemblyName = null; + if (tokens.Length > 1) + assemblyName = tokens [1].Trim (); + + if (string.IsNullOrWhiteSpace (typeName)) { + typeName = null; + assemblyName = null; + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs new file mode 100644 index 000000000000..bc743c65a188 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs @@ -0,0 +1,38 @@ +// +// TypePreserve.cs +// +// Author: +// Jb Evain (jb@nurv.fr) +// +// (C) 2007 Novell, 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. +// + +namespace Mono.Linker { + + public enum TypePreserve + { + Nothing, // This is actually Declaration + All, + Fields, + Methods + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs new file mode 100644 index 000000000000..ae271a0d4f7e --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs @@ -0,0 +1,241 @@ +using System; +using Mono.Cecil; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.Linker +{ + public static class TypeReferenceExtensions + { + public static TypeReference GetInflatedBaseType (this TypeReference type) + { + if (type == null) + return null; + + if (type.IsGenericParameter || type.IsByReference || type.IsPointer) + return null; + + var sentinelType = type as SentinelType; + if (sentinelType != null) + return sentinelType.ElementType.GetInflatedBaseType (); + + var pinnedType = type as PinnedType; + if (pinnedType != null) + return pinnedType.ElementType.GetInflatedBaseType (); + + var requiredModifierType = type as RequiredModifierType; + if (requiredModifierType != null) + return requiredModifierType.ElementType.GetInflatedBaseType (); + + var genericInstance = type as GenericInstanceType; + if (genericInstance != null) { + var baseType = type.Resolve ()?.BaseType; + var baseTypeGenericInstance = baseType as GenericInstanceType; + + if (baseTypeGenericInstance != null) + return InflateGenericType (genericInstance, baseType); + + return baseType; + } + + return type.Resolve ()?.BaseType; + } + + public static IEnumerable GetInflatedInterfaces (this TypeReference typeRef) + { + var typeDef = typeRef.Resolve (); + + if (typeDef?.HasInterfaces != true) + yield break; + + var genericInstance = typeRef as GenericInstanceType; + if (genericInstance != null) { + foreach (var interfaceImpl in typeDef.Interfaces) + yield return InflateGenericType (genericInstance, interfaceImpl.InterfaceType); + } else { + foreach (var interfaceImpl in typeDef.Interfaces) + yield return interfaceImpl.InterfaceType; + } + } + + public static TypeReference InflateGenericType (GenericInstanceType genericInstanceProvider, TypeReference typeToInflate) + { + var arrayType = typeToInflate as ArrayType; + if (arrayType != null) { + var inflatedElementType = InflateGenericType (genericInstanceProvider, arrayType.ElementType); + + if (inflatedElementType != arrayType.ElementType) + return new ArrayType (inflatedElementType, arrayType.Rank); + + return arrayType; + } + + var genericInst = typeToInflate as GenericInstanceType; + if (genericInst != null) + return MakeGenericType (genericInstanceProvider, genericInst); + + var genericParameter = typeToInflate as GenericParameter; + if (genericParameter != null) { + if (genericParameter.Owner is MethodReference) + return genericParameter; + + var elementType = genericInstanceProvider.ElementType.Resolve (); + var parameter = elementType.GenericParameters.Single (p => p == genericParameter); + return genericInstanceProvider.GenericArguments [parameter.Position]; + } + + var functionPointerType = typeToInflate as FunctionPointerType; + if (functionPointerType != null) { + var result = new FunctionPointerType (); + result.ReturnType = InflateGenericType (genericInstanceProvider, functionPointerType.ReturnType); + + for (int i = 0; i < functionPointerType.Parameters.Count; i++) { + var inflatedParameterType = InflateGenericType(genericInstanceProvider, functionPointerType.Parameters [i].ParameterType); + result.Parameters.Add (new ParameterDefinition (inflatedParameterType)); + } + + return result; + } + + var modifierType = typeToInflate as IModifierType; + if (modifierType != null) { + var modifier = InflateGenericType (genericInstanceProvider, modifierType.ModifierType); + var elementType = InflateGenericType (genericInstanceProvider, modifierType.ElementType); + + if (modifierType is OptionalModifierType) { + return new OptionalModifierType (modifier, elementType); + } + + return new RequiredModifierType (modifier, elementType); + } + + var pinnedType = typeToInflate as PinnedType; + if (pinnedType != null) { + var elementType = InflateGenericType (genericInstanceProvider, pinnedType.ElementType); + + if (elementType != pinnedType.ElementType) + return new PinnedType (elementType); + + return pinnedType; + } + + var pointerType = typeToInflate as PointerType; + if (pointerType != null) { + var elementType = InflateGenericType (genericInstanceProvider, pointerType.ElementType); + + if (elementType != pointerType.ElementType) + return new PointerType (elementType); + + return pointerType; + } + + var byReferenceType = typeToInflate as ByReferenceType; + if (byReferenceType != null) { + var elementType = InflateGenericType (genericInstanceProvider, byReferenceType.ElementType); + + if (elementType != byReferenceType.ElementType) + return new ByReferenceType (elementType); + + return byReferenceType; + } + + var sentinelType = typeToInflate as SentinelType; + if (sentinelType != null) { + var elementType = InflateGenericType (genericInstanceProvider, sentinelType.ElementType); + + if (elementType != sentinelType.ElementType) + return new SentinelType (elementType); + + return sentinelType; + } + + return typeToInflate; + } + + private static GenericInstanceType MakeGenericType (GenericInstanceType genericInstanceProvider, GenericInstanceType type) + { + var result = new GenericInstanceType (type.ElementType); + + for (var i = 0; i < type.GenericArguments.Count; ++i) { + result.GenericArguments.Add (InflateGenericType (genericInstanceProvider, type.GenericArguments [i])); + } + + return result; + } + + public static IEnumerable GetMethods (this TypeReference type) + { + var typeDef = type.Resolve (); + + if (typeDef?.HasMethods != true) + yield break; + + var genericInstanceType = type as GenericInstanceType; + if (genericInstanceType != null) { + foreach (var methodDef in typeDef.Methods) + yield return MakeMethodReferenceForGenericInstanceType (genericInstanceType, methodDef); + } else { + foreach (var method in typeDef.Methods) + yield return method; + } + } + + private static MethodReference MakeMethodReferenceForGenericInstanceType (GenericInstanceType genericInstanceType, MethodDefinition methodDef) + { + var method = new MethodReference (methodDef.Name, methodDef.ReturnType, genericInstanceType) { + HasThis = methodDef.HasThis, + ExplicitThis = methodDef.ExplicitThis, + CallingConvention = methodDef.CallingConvention + }; + + foreach (var parameter in methodDef.Parameters) + method.Parameters.Add (new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); + + foreach (var gp in methodDef.GenericParameters) + method.GenericParameters.Add (new GenericParameter (gp.Name, method)); + + return method; + } + + public static string ToCecilName (this string fullTypeName) + { + return fullTypeName.Replace ('+', '/'); + } + + public static bool HasDefaultConstructor (this TypeReference type) + { + foreach (var m in type.GetMethods ()) { + if (m.HasParameters) + continue; + + var definition = m.Resolve (); + if (definition?.IsDefaultConstructor () == true) + return true; + } + + return false; + } + + public static MethodReference GetDefaultInstanceConstructor (this TypeReference type) + { + foreach (var m in type.GetMethods ()) { + if (m.HasParameters) + continue; + + var definition = m.Resolve (); + if (!definition.IsDefaultConstructor ()) + continue; + + return m; + } + + throw new NotImplementedException (); + } + + public static bool IsTypeOf (this TypeReference type, string ns, string name) + { + return type.Name == name + && type.Namespace == ns; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs new file mode 100644 index 000000000000..4c96fc283693 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs @@ -0,0 +1,384 @@ +// +// XApiReader.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.XPath; + +using Mono.Cecil; +using Mono.Collections.Generic; + +namespace Mono.Linker { + + public class XApiReader { + + static readonly string _name = "name"; + static readonly string _ns = string.Empty; + + LinkContext _context; + XPathDocument _document; + IXApiVisitor _visitor; + + AssemblyDefinition _assembly; + string _namespace; + Stack _types = new Stack (); + StringBuilder _signature; + + public XApiReader (XPathDocument document, IXApiVisitor visitor) + { + _document = document; + _visitor = visitor; + } + + public void Process (LinkContext context) + { + _context = context; + ProcessAssemblies (_document.CreateNavigator ()); + } + + void OnAssembly (XPathNavigator nav) + { + _assembly = GetAssembly (nav); + + _visitor.OnAssembly (nav, _assembly); + + ProcessAttributes (nav); + ProcessNamespaces (nav); + } + + AssemblyDefinition GetAssembly (XPathNavigator nav) + { + AssemblyNameReference name = new AssemblyNameReference ( + GetName (nav), + new Version (GetAttribute (nav, "version"))); + + AssemblyDefinition assembly = _context.Resolve (name); + ProcessReferences (assembly); + return assembly; + } + + void ProcessReferences (AssemblyDefinition assembly) + { + foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences) + _context.Resolve (name); + } + + void OnAttribute (XPathNavigator nav) + { + _visitor.OnAttribute (nav); + } + + void PushType (TypeDefinition type) + { + _types.Push (type); + } + + TypeDefinition PeekType () + { + return _types.Peek (); + } + + TypeDefinition PopType () + { + return _types.Pop (); + } + + void OnNamespace (XPathNavigator nav) + { + _namespace = GetName (nav); + + ProcessClasses (nav); + } + + void OnClass (XPathNavigator nav) + { + string name = GetClassName (nav); + + TypeDefinition type = _assembly.MainModule.GetType (name); + if (type == null) + return; + + _visitor.OnClass (nav, type); + + PushType (type); + + ProcessAttributes (nav); + ProcessInterfaces (nav); + ProcessFields (nav); + ProcessMethods (nav); + ProcessConstructors (nav); + ProcessProperties (nav); + ProcessEvents (nav); + ProcessClasses (nav); + + PopType (); + } + + string GetClassName (XPathNavigator nav) + { + if (IsNestedClass ()) + return PeekType ().FullName + "/" + GetName (nav); + + return _namespace + "." + GetName (nav); + } + + bool IsNestedClass () + { + return _types.Count > 0; + } + + void OnField (XPathNavigator nav) + { + TypeDefinition declaring = PeekType (); + + FieldDefinition field = declaring.Fields.FirstOrDefault (f => f.Name == GetName (nav)); + if (field != null) + _visitor.OnField (nav, field); + + ProcessAttributes (nav); + } + + void OnInterface (XPathNavigator nav) + { + string name = GetName (nav); + + TypeDefinition type = _context.GetType (GetTypeName (name)); + if (type != null) + _visitor.OnInterface (nav, type); + } + + void OnMethod (XPathNavigator nav) + { + InitMethodSignature (nav); + + ProcessParameters (nav); + + string signature = GetMethodSignature (); + + MethodDefinition method = GetMethod (signature); + if (method != null) + _visitor.OnMethod (nav, method); + + ProcessAttributes (nav); + } + + MethodDefinition GetMethod (string signature) + { + return GetMethod (PeekType ().Methods, signature); + } + + static MethodDefinition GetMethod (Collection methods, string signature) + { + foreach (MethodDefinition method in methods) + if (signature == GetSignature (method)) + return method; + + return null; + } + + static string GetSignature (MethodDefinition method) + { + return method.ToString ().Replace ("<", "[").Replace (">", "]"); + } + + string GetMethodSignature () + { + _signature.Append (")"); + return _signature.ToString (); + } + + void InitMethodSignature (XPathNavigator nav) + { + _signature = new StringBuilder (); + + string returntype = GetAttribute (nav, "returntype"); + if (returntype == null || returntype.Length == 0) + returntype = "System.Void"; + + _signature.Append (NormalizeTypeName (returntype)); + _signature.Append (" "); + _signature.Append (PeekType ().FullName); + _signature.Append ("::"); + + string name = GetName (nav); + _signature.Append (GetMethodName (name)); + + _signature.Append ("("); + } + + static string GetMethodName (string name) + { + return GetStringBefore (name, "("); + } + + static string NormalizeTypeName (string name) + { + return name.Replace ("+", "/").Replace ("<", "[").Replace (">", "]"); + } + + static string GetTypeName (string name) + { + return GetStringBefore (NormalizeTypeName (name), "["); + } + + static string GetStringBefore (string str, string marker) + { + int pos = str.IndexOf (marker); + if (pos == -1) + return str; + + return str.Substring (0, pos); + } + + void OnParameter (XPathNavigator nav) + { + string type = GetAttribute (nav, "type"); + int pos = int.Parse (GetAttribute (nav, "position")); + + if (pos > 0) + _signature.Append (","); + _signature.Append (NormalizeTypeName (type)); + } + + void OnConstructor (XPathNavigator nav) + { + InitMethodSignature (nav); + + ProcessParameters (nav); + + string signature = GetMethodSignature (); + + MethodDefinition ctor = GetMethod (signature); + if (ctor != null) + _visitor.OnConstructor (nav, ctor); + + ProcessAttributes (nav); + } + + void OnProperty (XPathNavigator nav) + { + string name = GetName (nav); + TypeDefinition type = PeekType (); + + var property = type.Properties.FirstOrDefault (p => p.Name == name); + if (property != null) + _visitor.OnProperty (nav, property); + + ProcessAttributes (nav); + ProcessMethods (nav); + } + + void OnEvent (XPathNavigator nav) + { + string name = GetName (nav); + TypeDefinition type = PeekType (); + + EventDefinition evt = type.Events.FirstOrDefault (e => e.Name == name); + if (evt != null) + _visitor.OnEvent (nav, evt); + + ProcessAttributes (nav); + } + + void ProcessAssemblies (XPathNavigator nav) + { + ProcessChildren (nav, "assemblies//assembly", new OnChildren (OnAssembly)); + } + + void ProcessAttributes (XPathNavigator nav) + { + ProcessChildren (nav, "attributes//attribute", new OnChildren (OnAttribute)); + } + + void ProcessNamespaces (XPathNavigator nav) + { + ProcessChildren (nav, "namespaces//namespace", new OnChildren (OnNamespace)); + } + + void ProcessClasses (XPathNavigator nav) + { + ProcessChildren (nav, "classes//class", new OnChildren (OnClass)); + } + + void ProcessInterfaces (XPathNavigator nav) + { + ProcessChildren (nav, "interfaces//interface", new OnChildren (OnInterface)); + } + + void ProcessFields (XPathNavigator nav) + { + ProcessChildren (nav, "fields//field", new OnChildren (OnField)); + } + + void ProcessMethods (XPathNavigator nav) + { + ProcessChildren (nav, "methods//method", new OnChildren (OnMethod)); + } + + void ProcessConstructors (XPathNavigator nav) + { + ProcessChildren (nav, "constructors//constructor", new OnChildren (OnConstructor)); + } + + void ProcessParameters (XPathNavigator nav) + { + ProcessChildren (nav, "parameters//parameter", new OnChildren (OnParameter)); + } + + void ProcessProperties (XPathNavigator nav) + { + ProcessChildren (nav, "properties//property", new OnChildren (OnProperty)); + } + + void ProcessEvents (XPathNavigator nav) + { + ProcessChildren (nav, "events//event", new OnChildren (OnEvent)); + } + + static void ProcessChildren (XPathNavigator nav, string children, OnChildren action) + { + XPathNodeIterator iterator = nav.Select (children); + while (iterator.MoveNext ()) + action (iterator.Current); + } + + delegate void OnChildren (XPathNavigator nav); + + static string GetName (XPathNavigator nav) + { + return GetAttribute (nav, _name); + } + + static string GetAttribute (XPathNavigator nav, string attribute) + { + return nav.GetAttribute (attribute, _ns); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs new file mode 100644 index 000000000000..637b94c2aa1b --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs @@ -0,0 +1,215 @@ +// +// Tracer.cs +// +// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.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 Mono.Cecil; +using Mono.Linker.Steps; +using System; +using System.IO; +using System.IO.Compression; +using System.Xml; + +namespace Mono.Linker +{ + /// + /// Class which implements IDependencyRecorder and writes the dependencies into an XML file. + /// + public class XmlDependencyRecorder : IDependencyRecorder, IDisposable + { + public const string DefaultDependenciesFileName = "linker-dependencies.xml.gz"; + + private readonly LinkContext context; + private XmlWriter writer; + private Stream stream; + + public XmlDependencyRecorder (LinkContext context, string fileName = null) + { + this.context = context; + + XmlWriterSettings settings = new XmlWriterSettings { + Indent = true, + IndentChars = "\t" + }; + + if (fileName == null) + fileName = DefaultDependenciesFileName; + + if (string.IsNullOrEmpty (Path.GetDirectoryName (fileName)) && !string.IsNullOrEmpty (context.OutputDirectory)) { + fileName = Path.Combine (context.OutputDirectory, fileName); + Directory.CreateDirectory (context.OutputDirectory); + } + + var depsFile = File.OpenWrite (fileName); + + if (Path.GetExtension (fileName) == ".xml") + stream = depsFile; + else + stream = new GZipStream (depsFile, CompressionMode.Compress); + + writer = XmlWriter.Create (stream, settings); + writer.WriteStartDocument (); + writer.WriteStartElement ("dependencies"); + writer.WriteStartAttribute ("version"); + writer.WriteString ("1.2"); + writer.WriteEndAttribute (); + } + + public void Dispose () + { + if (writer == null) + return; + + writer.WriteEndElement (); + writer.WriteEndDocument (); + writer.Flush (); + writer.Dispose (); + stream.Dispose (); + writer = null; + stream = null; + } + + public void RecordDependency (object source, object target, bool marked) + { + if (!ShouldRecord (source) && !ShouldRecord (target)) + return; + + // This is a hack to work around a quirk of MarkStep that results in outputting ~6k edges even with the above ShouldRecord checks. + // What happens is that due to the method queueing in MarkStep, the dependency chain is broken in many cases. And in these cases + // we end up adding an edge for MarkStep -> + // This isn't particularly useful information since it's incomplete, but it's especially not useful in ReducedTracing mode when there is one of these for + // every class library method that was queued. + if (context.EnableReducedTracing && source is MarkStep && !ShouldRecord (target)) + return; + + // This is another hack to prevent useless information from being logged. With the introduction of interface sweeping there are a lot of edges such as + // `e="InterfaceImpl:Mono.Cecil.InterfaceImplementation"` which are useless information. Ideally we would format the interface implementation into a meaningful format + // however I don't think that is worth the effort at the moment. + if (target is InterfaceImplementation) + return; + + if (source != target) { + writer.WriteStartElement ("edge"); + if (marked) + writer.WriteAttributeString ("mark", "1"); + writer.WriteAttributeString ("b", TokenString (source)); + writer.WriteAttributeString ("e", TokenString (target)); + writer.WriteEndElement (); + } + } + + static bool IsAssemblyBound (TypeDefinition td) + { + do { + if (td.IsNestedPrivate || td.IsNestedAssembly || td.IsNestedFamilyAndAssembly) + return true; + + td = td.DeclaringType; + } while (td != null); + + return false; + } + + string TokenString (object o) + { + if (o == null) + return "N:null"; + + if (o is TypeReference t) { + bool addAssembly = true; + var td = t as TypeDefinition ?? t.Resolve (); + + if (td != null) { + addAssembly = td.IsNotPublic || IsAssemblyBound (td); + t = td; + } + + var addition = addAssembly ? $":{t.Module}" : ""; + + return $"{(o as IMetadataTokenProvider).MetadataToken.TokenType}:{o}{addition}"; + } + + if (o is IMetadataTokenProvider) + return (o as IMetadataTokenProvider).MetadataToken.TokenType + ":" + o; + + return "Other:" + o; + } + + bool WillAssemblyBeModified (AssemblyDefinition assembly) + { + switch (context.Annotations.GetAction (assembly)) { + case AssemblyAction.Link: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + return true; + default: + return false; + } + } + + bool ShouldRecord (object o) + { + if (!context.EnableReducedTracing) + return true; + + if (o is TypeDefinition t) + return WillAssemblyBeModified (t.Module.Assembly); + + if (o is IMemberDefinition m) + return WillAssemblyBeModified (m.DeclaringType.Module.Assembly); + + if (o is TypeReference typeRef) { + var resolved = typeRef.Resolve (); + + // Err on the side of caution if we can't resolve + if (resolved == null) + return true; + + return WillAssemblyBeModified (resolved.Module.Assembly); + } + + if (o is MemberReference mRef) { + var resolved = mRef.Resolve (); + + // Err on the side of caution if we can't resolve + if (resolved == null) + return true; + + return WillAssemblyBeModified (resolved.DeclaringType.Module.Assembly); + } + + if (o is ModuleDefinition module) + return WillAssemblyBeModified (module.Assembly); + + if (o is AssemblyDefinition assembly) + return WillAssemblyBeModified (assembly); + + if (o is ParameterDefinition parameter) { + if (parameter.Method is MethodDefinition parameterMethodDefinition) + return WillAssemblyBeModified (parameterMethodDefinition.DeclaringType.Module.Assembly); + } + + return true; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs new file mode 100644 index 000000000000..6a910a9d97fb --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public abstract class ApplyPreserveAttributeBase : BaseSubStep { + + // set 'removeAttribute' to true if you want the preserved attribute to be removed from the final assembly + protected abstract bool IsPreservedAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out bool removeAttribute); + + public override SubStepTargets Targets { + get { + return SubStepTargets.Type + | SubStepTargets.Field + | SubStepTargets.Method + | SubStepTargets.Property + | SubStepTargets.Event; + } + } + + public override bool IsActiveFor (AssemblyDefinition assembly) + { + return !Profile.IsSdkAssembly (assembly) && Annotations.GetAction (assembly) == AssemblyAction.Link; + } + + public override void ProcessType (TypeDefinition type) + { + TryApplyPreserveAttribute (type); + } + + public override void ProcessField (FieldDefinition field) + { + foreach (var attribute in GetPreserveAttributes (field)) + Mark (field, attribute); + } + + public override void ProcessMethod (MethodDefinition method) + { + MarkMethodIfPreserved (method); + } + + public override void ProcessProperty (PropertyDefinition property) + { + foreach (var attribute in GetPreserveAttributes (property)) { + MarkMethod (property.GetMethod, attribute); + MarkMethod (property.SetMethod, attribute); + } + } + + public override void ProcessEvent (EventDefinition @event) + { + foreach (var attribute in GetPreserveAttributes (@event)) { + MarkMethod (@event.AddMethod, attribute); + MarkMethod (@event.InvokeMethod, attribute); + MarkMethod (@event.RemoveMethod, attribute); + } + } + + void MarkMethodIfPreserved (MethodDefinition method) + { + foreach (var attribute in GetPreserveAttributes (method)) + MarkMethod (method, attribute); + } + + void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute) + { + if (method == null) + return; + + Mark (method, preserve_attribute); + Annotations.SetAction (method, MethodAction.Parse); + } + + void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute) + { + if (IsConditionalAttribute (preserve_attribute)) { + PreserveConditional (provider); + return; + } + + PreserveUnconditional (provider); + } + + void PreserveConditional (IMetadataTokenProvider provider) + { + var method = provider as MethodDefinition; + if (method == null) { + // workaround to support (uncommon but valid) conditional fields form [Preserve] + PreserveUnconditional (provider); + return; + } + + Annotations.AddPreservedMethod (method.DeclaringType, method); + } + + static bool IsConditionalAttribute (CustomAttribute attribute) + { + if (attribute == null) + return false; + + foreach (var named_argument in attribute.Fields) + if (named_argument.Name == "Conditional") + return (bool) named_argument.Argument.Value; + + return false; + } + + void PreserveUnconditional (IMetadataTokenProvider provider) + { + Annotations.Mark (provider); + + var member = provider as IMemberDefinition; + if (member == null || member.DeclaringType == null) + return; + + Mark (member.DeclaringType, null); + } + + void TryApplyPreserveAttribute (TypeDefinition type) + { + foreach (var attribute in GetPreserveAttributes (type)) { + Annotations.Mark (type); + + if (!attribute.HasFields) + continue; + + foreach (var named_argument in attribute.Fields) + if (named_argument.Name == "AllMembers" && (bool)named_argument.Argument.Value) + Annotations.SetPreserve (type, TypePreserve.All); + } + } + + List GetPreserveAttributes (ICustomAttributeProvider provider) + { + List attrs = new List (); + + if (!provider.HasCustomAttributes) + return attrs; + + var attributes = provider.CustomAttributes; + + for (int i = attributes.Count - 1; i >= 0; i--) { + var attribute = attributes [i]; + + bool remote_attribute; + if (!IsPreservedAttribute (provider, attribute, out remote_attribute)) + continue; + + attrs.Add (attribute); + if (remote_attribute) + attributes.RemoveAt (i); + } + + return attrs; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs new file mode 100644 index 000000000000..69958598dda2 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs @@ -0,0 +1,519 @@ +// +// MethodBodyRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// 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.Collections.Generic; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Tuner { + + public static class MethodBodyRocks { + + public static IEnumerable GetAllTypes (this ModuleDefinition self) + { + return self.Types.SelectMany (t => t.GetAllTypes ()); + } + + static IEnumerable GetAllTypes (this TypeDefinition self) + { + yield return self; + + if (!self.HasNestedTypes) + yield break; + + foreach (var type in self.NestedTypes.SelectMany (t => t.GetAllTypes ())) + yield return type; + } + + public static IEnumerable GetMethods (this TypeDefinition self) + { + return self.Methods.Where (m => !m.IsConstructor); + } + + public static IEnumerable GetConstructors (this TypeDefinition self) + { + return self.Methods.Where (m => m.IsConstructor); + } + + public static MethodDefinition GetTypeConstructor (this TypeDefinition self) + { + return self.GetConstructors ().FirstOrDefault (c => c.IsStatic); + } + + public static void SimplifyMacros (this MethodBody self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + foreach (var instruction in self.Instructions) { + if (instruction.OpCode.OpCodeType != OpCodeType.Macro) + continue; + + switch (instruction.OpCode.Code) { + case Code.Ldarg_0: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (0)); + break; + case Code.Ldarg_1: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (1)); + break; + case Code.Ldarg_2: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (2)); + break; + case Code.Ldarg_3: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (3)); + break; + case Code.Ldloc_0: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [0]); + break; + case Code.Ldloc_1: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [1]); + break; + case Code.Ldloc_2: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [2]); + break; + case Code.Ldloc_3: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [3]); + break; + case Code.Stloc_0: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [0]); + break; + case Code.Stloc_1: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [1]); + break; + case Code.Stloc_2: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [2]); + break; + case Code.Stloc_3: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [3]); + break; + case Code.Ldarg_S: + instruction.OpCode = OpCodes.Ldarg; + break; + case Code.Ldarga_S: + instruction.OpCode = OpCodes.Ldarga; + break; + case Code.Starg_S: + instruction.OpCode = OpCodes.Starg; + break; + case Code.Ldloc_S: + instruction.OpCode = OpCodes.Ldloc; + break; + case Code.Ldloca_S: + instruction.OpCode = OpCodes.Ldloca; + break; + case Code.Stloc_S: + instruction.OpCode = OpCodes.Stloc; + break; + case Code.Ldc_I4_M1: + ExpandMacro (instruction, OpCodes.Ldc_I4, -1); + break; + case Code.Ldc_I4_0: + ExpandMacro (instruction, OpCodes.Ldc_I4, 0); + break; + case Code.Ldc_I4_1: + ExpandMacro (instruction, OpCodes.Ldc_I4, 1); + break; + case Code.Ldc_I4_2: + ExpandMacro (instruction, OpCodes.Ldc_I4, 2); + break; + case Code.Ldc_I4_3: + ExpandMacro (instruction, OpCodes.Ldc_I4, 3); + break; + case Code.Ldc_I4_4: + ExpandMacro (instruction, OpCodes.Ldc_I4, 4); + break; + case Code.Ldc_I4_5: + ExpandMacro (instruction, OpCodes.Ldc_I4, 5); + break; + case Code.Ldc_I4_6: + ExpandMacro (instruction, OpCodes.Ldc_I4, 6); + break; + case Code.Ldc_I4_7: + ExpandMacro (instruction, OpCodes.Ldc_I4, 7); + break; + case Code.Ldc_I4_8: + ExpandMacro (instruction, OpCodes.Ldc_I4, 8); + break; + case Code.Ldc_I4_S: + ExpandMacro (instruction, OpCodes.Ldc_I4, (int) (sbyte) instruction.Operand); + break; + case Code.Br_S: + instruction.OpCode = OpCodes.Br; + break; + case Code.Brfalse_S: + instruction.OpCode = OpCodes.Brfalse; + break; + case Code.Brtrue_S: + instruction.OpCode = OpCodes.Brtrue; + break; + case Code.Beq_S: + instruction.OpCode = OpCodes.Beq; + break; + case Code.Bge_S: + instruction.OpCode = OpCodes.Bge; + break; + case Code.Bgt_S: + instruction.OpCode = OpCodes.Bgt; + break; + case Code.Ble_S: + instruction.OpCode = OpCodes.Ble; + break; + case Code.Blt_S: + instruction.OpCode = OpCodes.Blt; + break; + case Code.Bne_Un_S: + instruction.OpCode = OpCodes.Bne_Un; + break; + case Code.Bge_Un_S: + instruction.OpCode = OpCodes.Bge_Un; + break; + case Code.Bgt_Un_S: + instruction.OpCode = OpCodes.Bgt_Un; + break; + case Code.Ble_Un_S: + instruction.OpCode = OpCodes.Ble_Un; + break; + case Code.Blt_Un_S: + instruction.OpCode = OpCodes.Blt_Un; + break; + case Code.Leave_S: + instruction.OpCode = OpCodes.Leave; + break; + } + } + } + + static void ExpandMacro (Instruction instruction, OpCode opcode, object operand) + { + instruction.OpCode = opcode; + instruction.Operand = operand; + } + + static void MakeMacro (Instruction instruction, OpCode opcode) + { + instruction.OpCode = opcode; + instruction.Operand = null; + } + + public static void OptimizeMacros (this MethodBody self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + var method = self.Method; + + foreach (var instruction in self.Instructions) { + int index; + switch (instruction.OpCode.Code) { + case Code.Ldarg: + index = ((ParameterDefinition) instruction.Operand).Index; + if (index == -1 && instruction.Operand == self.ThisParameter) + index = 0; + else if (method.HasThis) + index++; + + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Ldarg_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldarg_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldarg_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldarg_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldarg_S, instruction.Operand); + break; + } + break; + case Code.Ldloc: + index = ((VariableDefinition) instruction.Operand).Index; + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Ldloc_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldloc_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldloc_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldloc_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldloc_S, instruction.Operand); + break; + } + break; + case Code.Stloc: + index = ((VariableDefinition) instruction.Operand).Index; + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Stloc_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Stloc_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Stloc_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Stloc_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Stloc_S, instruction.Operand); + break; + } + break; + case Code.Ldarga: + index = ((ParameterDefinition) instruction.Operand).Index; + if (index == -1 && instruction.Operand == self.ThisParameter) + index = 0; + else if (method.HasThis) + index++; + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldarga_S, instruction.Operand); + break; + case Code.Ldloca: + if (((VariableDefinition) instruction.Operand).Index < 256) + ExpandMacro (instruction, OpCodes.Ldloca_S, instruction.Operand); + break; + case Code.Ldc_I4: + int i = (int) instruction.Operand; + switch (i) { + case -1: + MakeMacro (instruction, OpCodes.Ldc_I4_M1); + break; + case 0: + MakeMacro (instruction, OpCodes.Ldc_I4_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldc_I4_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldc_I4_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldc_I4_3); + break; + case 4: + MakeMacro (instruction, OpCodes.Ldc_I4_4); + break; + case 5: + MakeMacro (instruction, OpCodes.Ldc_I4_5); + break; + case 6: + MakeMacro (instruction, OpCodes.Ldc_I4_6); + break; + case 7: + MakeMacro (instruction, OpCodes.Ldc_I4_7); + break; + case 8: + MakeMacro (instruction, OpCodes.Ldc_I4_8); + break; + default: + if (i >= -128 && i < 128) + ExpandMacro (instruction, OpCodes.Ldc_I4_S, (sbyte) i); + break; + } + break; + } + } + + OptimizeBranches (self); + } + + static void OptimizeBranches (MethodBody body) + { + ComputeOffsets (body); + + foreach (var instruction in body.Instructions) { + if (instruction.OpCode.OperandType != OperandType.InlineBrTarget) + continue; + + if (OptimizeBranch (instruction)) + ComputeOffsets (body); + } + } + + static bool OptimizeBranch (Instruction instruction) + { + var offset = ((Instruction) instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4); + if (!(offset >= -128 && offset <= 127)) + return false; + + switch (instruction.OpCode.Code) { + case Code.Br: + instruction.OpCode = OpCodes.Br_S; + break; + case Code.Brfalse: + instruction.OpCode = OpCodes.Brfalse_S; + break; + case Code.Brtrue: + instruction.OpCode = OpCodes.Brtrue_S; + break; + case Code.Beq: + instruction.OpCode = OpCodes.Beq_S; + break; + case Code.Bge: + instruction.OpCode = OpCodes.Bge_S; + break; + case Code.Bgt: + instruction.OpCode = OpCodes.Bgt_S; + break; + case Code.Ble: + instruction.OpCode = OpCodes.Ble_S; + break; + case Code.Blt: + instruction.OpCode = OpCodes.Blt_S; + break; + case Code.Bne_Un: + instruction.OpCode = OpCodes.Bne_Un_S; + break; + case Code.Bge_Un: + instruction.OpCode = OpCodes.Bge_Un_S; + break; + case Code.Bgt_Un: + instruction.OpCode = OpCodes.Bgt_Un_S; + break; + case Code.Ble_Un: + instruction.OpCode = OpCodes.Ble_Un_S; + break; + case Code.Blt_Un: + instruction.OpCode = OpCodes.Blt_Un_S; + break; + case Code.Leave: + instruction.OpCode = OpCodes.Leave_S; + break; + } + + return true; + } + + static void ComputeOffsets (MethodBody body) + { + var offset = 0; + foreach (var instruction in body.Instructions) { + instruction.Offset = offset; + offset += instruction.GetSize (); + } + } + + public static ParameterDefinition GetParameter (this MethodBody self, int index) + { + var method = self.Method; + + if (method.HasThis) { + if (index == 0) + return self.ThisParameter; + + index--; + } + + var parameters = method.Parameters; + + if (index < 0 || index >= parameters.Count) + return null; + + return parameters [index]; + } + + public static bool Implements (this TypeReference self, string interfaceName) + { + if (interfaceName == null) + throw new ArgumentNullException ("interfaceName"); + if (self == null) + return false; + + TypeDefinition type = self.Resolve (); + if (type == null) + return false; // not enough information available + + // special case, check if we implement ourselves + if (type.IsInterface && (type.FullName == interfaceName)) + return true; + + return Implements (type, interfaceName, (interfaceName.IndexOf ('`') >= 0)); + } + + public static bool Implements (TypeDefinition type, string interfaceName, bool generic) + { + while (type != null) { + // does the type implements it itself + if (type.HasInterfaces) { + 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.InterfaceType.Resolve (), interfaceName, generic)) + return true; + } + } + + type = type.BaseType != null ? type.BaseType.Resolve () : null; + } + return false; + } + + public static bool Inherits (this TypeReference self, string @namespace, string name) + { + if (@namespace == null) + throw new ArgumentNullException ("namespace"); + if (name == null) + throw new ArgumentNullException ("name"); + if (self == null) + return false; + + TypeReference current = self.Resolve (); + while (current != null) { + if (current.Is (@namespace, name)) + return true; + if (current.Is ("System", "Object")) + return false; + + TypeDefinition td = current.Resolve (); + if (td == null) + return false; // could not resolve type + current = td.BaseType; + } + return false; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs new file mode 100644 index 000000000000..1bb6d6fb0e14 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Tuner { + + public class CustomizeActions : BaseStep { + + readonly bool link_sdk_only; + readonly HashSet skipped_assemblies; + + public CustomizeActions (bool link_sdk_only, IEnumerable skipped_assemblies) + { + this.link_sdk_only = link_sdk_only; + this.skipped_assemblies = new HashSet (skipped_assemblies); + } + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + if (!IsSkipped (assembly) && IsLinked (assembly)) { + if (!Annotations.HasAction (assembly)) // stray assembly not picked up when resolving references + Annotations.SetAction (assembly, AssemblyAction.Link); + return; + } + ProcessUserAssembly (assembly); + } + + protected virtual bool IsPreservedAttribute (CustomAttribute attribute) + { + // [assembly: Preserve (type)] does not preserve all the code in the assembly, in fact it might + // not preserve anything in _this_ assembly, but something in a separate assembly (reference) + if (attribute.HasConstructorArguments) + return false; + return (attribute.AttributeType.Name == "PreserveAttribute"); + } + + protected virtual bool IsLinkerSafeAttribute (CustomAttribute attribute) + { + return (attribute.AttributeType.Name == "LinkerSafeAttribute"); + } + + const ModuleAttributes Supported = ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit | + ModuleAttributes.Preferred32Bit | ModuleAttributes.StrongNameSigned; + + protected virtual bool IsSkipped (AssemblyDefinition assembly) + { + // Cecil can't save back mixed-mode assemblies - so we can't link them + if ((assembly.MainModule.Attributes & ~Supported) != 0) + return true; + + if (assembly.HasCustomAttributes) { + foreach (var ca in assembly.CustomAttributes) { + if (IsPreservedAttribute (ca)) + return true; + } + } + return skipped_assemblies.Contains (assembly.Name.Name); + } + + protected virtual bool IsLinked (AssemblyDefinition assembly) + { + // LinkAll + if (!link_sdk_only) + return true; + // Link SDK : applies to BCL/SDK and product assembly (e.g. monotouch.dll) + if (Profile.IsSdkAssembly (assembly)) + return true; + if (Profile.IsProductAssembly (assembly)) + return true; + // the assembly can be marked with [LinkAssembly] + if (assembly.HasCustomAttributes) { + foreach (var ca in assembly.CustomAttributes) { + if (IsLinkerSafeAttribute (ca)) + return true; + } + } + return false; + } + + protected void ProcessUserAssembly (AssemblyDefinition assembly) + { + ResolveFromAssemblyStep.ProcessLibrary (Context, assembly); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs new file mode 100644 index 000000000000..be1674044082 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs @@ -0,0 +1,310 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; + +namespace Mono.Tuner { + + [Flags] + public enum SubStepTargets { + None = 0, + + Assembly = 1, + Type = 2, + Field = 4, + Method = 8, + Property = 16, + Event = 32, + } + + public interface ISubStep { + + SubStepTargets Targets { get; } + + void Initialize (LinkContext context); + bool IsActiveFor (AssemblyDefinition assembly); + + void ProcessAssembly (AssemblyDefinition assembly); + void ProcessType (TypeDefinition type); + void ProcessField (FieldDefinition field); + void ProcessMethod (MethodDefinition method); + void ProcessProperty (PropertyDefinition property); + void ProcessEvent (EventDefinition @event); + } + + public abstract class BaseSubStep : ISubStep { + + protected LinkContext context; + + public AnnotationStore Annotations { + get { return context.Annotations; } + } + + public abstract SubStepTargets Targets { get; } + + public virtual void Initialize (LinkContext context) + { + this.context = context; + } + + public virtual bool IsActiveFor (AssemblyDefinition assembly) + { + return true; + } + + public virtual void ProcessAssembly (AssemblyDefinition assembly) + { + } + + public virtual void ProcessType (TypeDefinition type) + { + } + + public virtual void ProcessField (FieldDefinition field) + { + } + + public virtual void ProcessMethod (MethodDefinition method) + { + } + + public virtual void ProcessProperty (PropertyDefinition property) + { + } + + public virtual void ProcessEvent (EventDefinition @event) + { + } + } + + public class SubStepDispatcher : IStep, IEnumerable { + + List substeps = new List (); + + List on_assemblies; + List on_types; + List on_fields; + List on_methods; + List on_properties; + List on_events; + + Tracer tracer; + + public void Add (ISubStep substep) + { + substeps.Add (substep); + } + + public void Process (LinkContext context) + { + tracer = context.Tracer; + + InitializeSubSteps (context); + + BrowseAssemblies (context.GetAssemblies ()); + } + + void Push (ISubStep subStep) + { + if (tracer != null) + tracer.Push (subStep); + } + + void Pop () + { + if (tracer != null) + tracer.Pop (); + } + + static bool HasSubSteps (List substeps) + { + return substeps != null && substeps.Count > 0; + } + + void BrowseAssemblies (IEnumerable assemblies) + { + foreach (var assembly in assemblies) { + CategorizeSubSteps (assembly); + + if (HasSubSteps (on_assemblies)) + DispatchAssembly (assembly); + + if (!ShouldDispatchTypes ()) + continue; + + BrowseTypes (assembly.MainModule.Types); + } + } + + bool ShouldDispatchTypes () + { + return HasSubSteps (on_types) + || HasSubSteps (on_fields) + || HasSubSteps (on_methods) + || HasSubSteps (on_properties) + || HasSubSteps (on_events); + } + + void BrowseTypes (ICollection types) + { + foreach (TypeDefinition type in types) { + DispatchType (type); + + if (type.HasFields && HasSubSteps (on_fields)) + BrowseFields (type.Fields); + + if (type.HasMethods && HasSubSteps (on_methods)) + BrowseMethods (type.Methods); + + if (type.HasProperties && HasSubSteps (on_properties)) + BrowseProperties (type.Properties); + + if (type.HasEvents && HasSubSteps (on_events)) + BrowseEvents (type.Events); + + if (type.HasNestedTypes) + BrowseTypes (type.NestedTypes); + } + } + + void BrowseFields (ICollection fields) + { + foreach (FieldDefinition field in fields) + DispatchField (field); + } + + void BrowseMethods (ICollection methods) + { + foreach (MethodDefinition method in methods) + DispatchMethod (method); + } + + void BrowseProperties (ICollection properties) + { + foreach (PropertyDefinition property in properties) + DispatchProperty (property); + } + + void BrowseEvents (ICollection events) + { + foreach (EventDefinition @event in events) + DispatchEvent (@event); + } + + void DispatchAssembly (AssemblyDefinition assembly) + { + foreach (var substep in on_assemblies) { + Push (substep); + substep.ProcessAssembly (assembly); + Pop (); + } + } + + void DispatchType (TypeDefinition type) + { + foreach (var substep in on_types) { + Push (substep); + substep.ProcessType (type); + Pop (); + } + } + + void DispatchField (FieldDefinition field) + { + foreach (var substep in on_fields) { + Push (substep); + substep.ProcessField (field); + Pop (); + } + } + + void DispatchMethod (MethodDefinition method) + { + foreach (var substep in on_methods) { + Push (substep); + substep.ProcessMethod (method); + Pop (); + } + } + + void DispatchProperty (PropertyDefinition property) + { + foreach (var substep in on_properties) { + Push (substep); + substep.ProcessProperty (property); + Pop (); + } + } + + void DispatchEvent (EventDefinition @event) + { + foreach (var substep in on_events) { + Push (substep); + substep.ProcessEvent (@event); + Pop (); + } + } + + void InitializeSubSteps (LinkContext context) + { + foreach (var substep in substeps) + substep.Initialize (context); + } + + void CategorizeSubSteps (AssemblyDefinition assembly) + { + on_assemblies = null; + on_types = null; + on_fields = null; + on_methods = null; + on_properties = null; + on_events = null; + + foreach (var substep in substeps) + CategorizeSubStep (substep, assembly); + } + + void CategorizeSubStep (ISubStep substep, AssemblyDefinition assembly) + { + if (!substep.IsActiveFor (assembly)) + return; + + CategorizeTarget (substep, SubStepTargets.Assembly, ref on_assemblies); + CategorizeTarget (substep, SubStepTargets.Type, ref on_types); + CategorizeTarget (substep, SubStepTargets.Field, ref on_fields); + CategorizeTarget (substep, SubStepTargets.Method, ref on_methods); + CategorizeTarget (substep, SubStepTargets.Property, ref on_properties); + CategorizeTarget (substep, SubStepTargets.Event, ref on_events); + } + + static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List list) + { + if (!Targets (substep, target)) + return; + + if (list == null) + list = new List (); + + list.Add (substep); + } + + static bool Targets (ISubStep substep, SubStepTargets target) + { + return (substep.Targets & target) == target; + } + + IEnumerator IEnumerable.GetEnumerator () + { + return GetEnumerator (); + } + + public IEnumerator GetEnumerator () + { + return substeps.GetEnumerator (); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs new file mode 100644 index 000000000000..3e3b312133b6 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Mono.Linker; + +namespace Mono.Tuner { + + public static partial class Extensions { + + public static bool TryGetLinkedAssembly (this LinkContext context, string name, out AssemblyDefinition assembly) + { + assembly = GetAssembly (context, name); + if (assembly == null) + return false; + + return context.Annotations.GetAction (assembly) == AssemblyAction.Link; + } + + public static AssemblyDefinition GetAssembly (this LinkContext context, string assembly_name) + { + foreach (var assembly in context.GetAssemblies ()) + if (assembly.Name.Name == assembly_name) + return assembly; + + return null; + } + + // note: direct check, no inheritance + public static bool Is (this TypeReference type, string @namespace, string name) + { + return ((type != null) && (type.Name == name) && (type.Namespace == @namespace)); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/FixModuleFlags.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/FixModuleFlags.cs new file mode 100644 index 000000000000..2bb01ab9bc50 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/FixModuleFlags.cs @@ -0,0 +1,20 @@ +using System; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public class FixModuleFlags : BaseStep { + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + if (Annotations.GetAction (assembly) != AssemblyAction.Link) + return; + + assembly.MainModule.Attributes = ModuleAttributes.ILOnly; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs new file mode 100644 index 000000000000..18dbe7ff2514 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Tuner { + + public class PreserveCrypto : IStep { + + AnnotationStore annotations; + + public void Process (LinkContext context) + { + annotations = context.Annotations; + + ProcessCorlib (context); + ProcessSystemCore (context); + } + + void ProcessCorlib (LinkContext context) + { + AssemblyDefinition corlib; + if (!context.TryGetLinkedAssembly ("mscorlib", out corlib)) + return; + + AddPreserveInfo (corlib, "DES", "DESCryptoServiceProvider"); + AddPreserveInfo (corlib, "DSA", "DSACryptoServiceProvider"); + AddPreserveInfo (corlib, "RandomNumberGenerator", "RNGCryptoServiceProvider"); + AddPreserveInfo (corlib, "SHA1", "SHA1CryptoServiceProvider"); + AddPreserveInfo (corlib, "SHA1", "SHA1Managed"); + AddPreserveInfo (corlib, "MD5", "MD5CryptoServiceProvider"); + AddPreserveInfo (corlib, "RC2", "RC2CryptoServiceProvider"); + AddPreserveInfo (corlib, "TripleDES", "TripleDESCryptoServiceProvider"); + + AddPreserveInfo (corlib, "Rijndael", "RijndaelManaged"); + AddPreserveInfo (corlib, "RIPEMD160", "RIPEMD160Managed"); + AddPreserveInfo (corlib, "SHA256", "SHA256Managed"); + AddPreserveInfo (corlib, "SHA384", "SHA384Managed"); + AddPreserveInfo (corlib, "SHA512", "SHA512Managed"); + + AddPreserveInfo (corlib, "HMAC", "HMACMD5"); + AddPreserveInfo (corlib, "HMAC", "HMACRIPEMD160"); + AddPreserveInfo (corlib, "HMAC", "HMACSHA1"); + AddPreserveInfo (corlib, "HMAC", "HMACSHA256"); + AddPreserveInfo (corlib, "HMAC", "HMACSHA384"); + AddPreserveInfo (corlib, "HMAC", "HMACSHA512"); + + AddPreserveInfo (corlib, "HMACMD5", "MD5CryptoServiceProvider"); + AddPreserveInfo (corlib, "HMACRIPEMD160", "RIPEMD160Managed"); + AddPreserveInfo (corlib, "HMACSHA1", "SHA1CryptoServiceProvider"); + AddPreserveInfo (corlib, "HMACSHA1", "SHA1Managed"); + AddPreserveInfo (corlib, "HMACSHA256", "SHA256Managed"); + AddPreserveInfo (corlib, "HMACSHA384", "SHA384Managed"); + AddPreserveInfo (corlib, "HMACSHA512", "SHA512Managed"); + + TryAddPreserveInfo (corlib, "Aes", "AesManaged"); + + var corlibAes = GetCryptoType (corlib, "Aes"); + Preserve (corlibAes, GetCryptoType (corlib, "AesManaged")); + + AssemblyDefinition syscore; + if (context.TryGetLinkedAssembly ("System.Core", out syscore)) + Preserve (corlibAes, GetCryptoType (syscore, "AesCryptoServiceProvider")); + } + + void ProcessSystemCore (LinkContext context) + { + AssemblyDefinition syscore; + if (!context.TryGetLinkedAssembly ("System.Core", out syscore)) + return; + + // AddPreserveInfo (syscore, "Aes", "AesCryptoServiceProvider"); + TryAddPreserveInfo (syscore, "Aes", "AesManaged"); + } + + bool TryAddPreserveInfo (AssemblyDefinition assembly, string name, string type) + { + var marker = GetCryptoType (assembly, name); + if (marker == null) + return false; + + var implementation = GetCryptoType (assembly, type); + if (implementation == null) + return false; + + Preserve (marker, implementation); + return true; + } + + void AddPreserveInfo (AssemblyDefinition assembly, string name, string type) + { + var marker = GetCryptoType (assembly, name); + if (marker == null) + throw new ArgumentException (name); + + var implementation = GetCryptoType (assembly, type); + if (implementation == null) + throw new ArgumentException (type); + + Preserve (marker, implementation); + } + + void Preserve (TypeDefinition marker, TypeDefinition implementation) + { + if (marker == null || implementation == null) + return; + foreach (var constructor in implementation.GetConstructors ()) + annotations.AddPreservedMethod (marker, constructor); + } + + TypeDefinition GetCryptoType (AssemblyDefinition assembly, string name) + { + return assembly.MainModule.GetType ("System.Security.Cryptography." + name); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs new file mode 100644 index 000000000000..bdb04a94db23 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs @@ -0,0 +1,90 @@ +using System; + +using Mono.Linker; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public class PreserveSoapHttpClients : BaseSubStep { + + public override SubStepTargets Targets { + get { return SubStepTargets.Type; } + } + + public override bool IsActiveFor (AssemblyDefinition assembly) + { + return Annotations.GetAction (assembly) == AssemblyAction.Link && !Profile.IsSdkAssembly (assembly); + } + + public override void ProcessType (TypeDefinition type) + { + if (IsWebServiceClient (type)) + PreserveClient (type); + } + + void PreserveClient (TypeDefinition type) + { + if (!type.HasMethods) + return; + + foreach (MethodDefinition method in type.Methods) { + string sync_method; + if (!TryExtractSyncMethod (method, out sync_method)) + continue; + + AddPreservedMethod (method, sync_method); + } + } + + void AddPreservedMethod (MethodDefinition target, string methodName) + { + foreach (MethodDefinition method in target.DeclaringType.Methods) + if (method.Name == methodName) + Annotations.AddPreservedMethod (target, method); + } + + static bool TryExtractSyncMethod (MethodDefinition method, out string sync_method) + { + if (TryExtractPrefixedMethodName ("Begin", method.Name, out sync_method)) + return true; + + if (TryExtractPrefixedMethodName ("End", method.Name, out sync_method)) + return true; + + if (TryExtractSuffixedMethodName ("Async", method.Name, out sync_method)) + return true; + + return false; + } + + static bool TryExtractPrefixedMethodName (string prefix, string fullName, out string methodName) + { + methodName = null; + + int pos = fullName.IndexOf (prefix, StringComparison.Ordinal); + if (pos == -1) + return false; + + methodName = fullName.Substring (prefix.Length); + return true; + } + + static bool TryExtractSuffixedMethodName (string suffix, string fullName, out string methodName) + { + methodName = null; + + int pos = fullName.LastIndexOf (suffix, StringComparison.Ordinal); + if (pos == -1) + return false; + + methodName = fullName.Substring (0, pos); + return true; + } + + static bool IsWebServiceClient (TypeDefinition type) + { + return type.Inherits ("System.Web.Services.Protocols", "SoapHttpClientProtocol"); + } + } +} \ No newline at end of file diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs new file mode 100644 index 000000000000..54cfffa64f18 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public abstract class Profile { + + static Profile current; + + public static Profile Current { + get { + if (current != null) + return current; + + current = CreateProfile ("MonoTouch"); + if (current != null) + return current; + + current = CreateProfile ("MonoDroid"); + if (current != null) + return current; + + current = CreateProfile ("MonoMac"); + if (current != null) + return current; + + throw new NotSupportedException ("No active profile"); + } + set { + current = value; + } + } + + static Profile CreateProfile (string name) + { + var type = Type.GetType (string.Format ("{0}.Tuner.{0}Profile", name)); + if (type == null) + return null; + + return (Profile) Activator.CreateInstance (type); + } + + public static bool IsSdkAssembly (AssemblyDefinition assembly) + { + return Current.IsSdk (assembly); + } + + public static bool IsSdkAssembly (string assemblyName) + { + return Current.IsSdk (assemblyName); + } + + public static bool IsProductAssembly (AssemblyDefinition assembly) + { + return Current.IsProduct (assembly); + } + + public static bool IsProductAssembly (string assemblyName) + { + return Current.IsProduct (assemblyName); + } + + protected virtual bool IsSdk (AssemblyDefinition assembly) + { + return IsSdk (assembly.Name.Name); + } + + protected virtual bool IsProduct (AssemblyDefinition assembly) + { + return IsProduct (assembly.Name.Name); + } + + protected abstract bool IsSdk (string assemblyName); + protected abstract bool IsProduct (string assemblyName); + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveAttributesBase.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveAttributesBase.cs new file mode 100644 index 000000000000..61101809fd47 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveAttributesBase.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Tuner; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public abstract class RemoveAttributesBase : BaseSubStep { + + public override SubStepTargets Targets { + get { + return SubStepTargets.Assembly + | SubStepTargets.Type + | SubStepTargets.Field + | SubStepTargets.Method + | SubStepTargets.Property + | SubStepTargets.Event; + } + } + + public override bool IsActiveFor (AssemblyDefinition assembly) + { + return Annotations.GetAction (assembly) == AssemblyAction.Link; + } + + public override void ProcessAssembly (AssemblyDefinition assembly) + { + ProcessAttributeProvider (assembly); + ProcessAttributeProvider (assembly.MainModule); + } + + public override void ProcessType (TypeDefinition type) + { + ProcessAttributeProvider (type); + + if (type.HasGenericParameters) + ProcessAttributeProviderCollection (type.GenericParameters); + } + + void ProcessAttributeProviderCollection (IList list) + { + for (int i = 0; i < list.Count; i++) + ProcessAttributeProvider ((ICustomAttributeProvider) list [i]); + } + + public override void ProcessField (FieldDefinition field) + { + ProcessAttributeProvider (field); + } + + public override void ProcessMethod (MethodDefinition method) + { + ProcessMethodAttributeProvider (method); + } + + void ProcessMethodAttributeProvider (MethodDefinition method) + { + ProcessAttributeProvider (method); + ProcessAttributeProvider (method.MethodReturnType); + + if (method.HasParameters) + ProcessAttributeProviderCollection (method.Parameters); + + if (method.HasGenericParameters) + ProcessAttributeProviderCollection (method.GenericParameters); + } + + public override void ProcessProperty (PropertyDefinition property) + { + ProcessAttributeProvider (property); + } + + public override void ProcessEvent (EventDefinition @event) + { + ProcessAttributeProvider (@event); + } + + void ProcessAttributeProvider (ICustomAttributeProvider provider) + { + if (!provider.HasCustomAttributes) + return; + + for (int i = 0; i < provider.CustomAttributes.Count; i++) { + var attrib = provider.CustomAttributes [i]; + if (!IsRemovedAttribute (attrib)) + continue; + + WillRemoveAttribute (provider, attrib); + provider.CustomAttributes.RemoveAt (i--); + } + } + + protected abstract bool IsRemovedAttribute (CustomAttribute attribute); + protected virtual void WillRemoveAttribute (ICustomAttributeProvider provider, CustomAttribute attribute) { } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs new file mode 100644 index 000000000000..19c638615da5 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs @@ -0,0 +1,63 @@ +using System; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public class RemoveResources : IStep { + + readonly I18nAssemblies assemblies; + + public RemoveResources (I18nAssemblies assemblies) + { + this.assemblies = assemblies; + } + + public virtual void Process (LinkContext context) + { + AssemblyDefinition assembly; + if (!context.TryGetLinkedAssembly ("mscorlib", out assembly)) + return; + + // skip this if we're not linking mscorlib, e.g. --linkskip=mscorlib + if (context.Annotations.GetAction (assembly) != AssemblyAction.Link) + return; + + var resources = assembly.MainModule.Resources; + + for (int i = 0; i < resources.Count; i++) { + var resource = resources [i] as EmbeddedResource; + if (resource == null) + continue; + + if (RemoveResource (resource.Name)) + resources.RemoveAt(i--); + } + } + + bool RemoveResource (string name) + { + switch (name) { + case "mscorlib.xml": + return true; + case "collation.core.bin": + case "collation.tailoring.bin": + return false; + default: + if (!name.Contains("cjk")) + return false; + if (IncludeCJK()) + return false; + return true; + } + } + + bool IncludeCJK () + { + return (assemblies & I18nAssemblies.CJK) != 0; + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveSecurity.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveSecurity.cs new file mode 100644 index 000000000000..2704564a65e1 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveSecurity.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Mono.Linker; +using Mono.Linker.Steps; + +using Mono.Cecil; + +namespace Mono.Tuner { + + public class RemoveSecurity : BaseSubStep { + + public override SubStepTargets Targets { + get { + return SubStepTargets.Assembly + | SubStepTargets.Type + | SubStepTargets.Method; + } + } + + public override bool IsActiveFor (AssemblyDefinition assembly) + { + return Annotations.GetAction (assembly) == AssemblyAction.Link; + } + + public override void ProcessAssembly (AssemblyDefinition assembly) + { + ProcessSecurityProvider (assembly); + } + + public override void ProcessType (TypeDefinition type) + { + ProcessSecurityProvider (type); + } + + public override void ProcessMethod (MethodDefinition method) + { + ProcessSecurityProvider (method); + } + + static void ProcessSecurityProvider (ISecurityDeclarationProvider provider) + { + if (!provider.HasSecurityDeclarations) + return; + + provider.SecurityDeclarations.Clear (); + } + } +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/TunerAnnotations.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/TunerAnnotations.cs new file mode 100644 index 000000000000..2107ac4a0f59 --- /dev/null +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/TunerAnnotations.cs @@ -0,0 +1,55 @@ +// +// TunerAnnotations.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2007 Novell, 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 Mono.Cecil; +using Mono.Linker; + +namespace Mono.Tuner { + + public class TunerAnnotations { + + static readonly object _internalizedKey = new object (); + + public static void Internalized (LinkContext context, IMetadataTokenProvider provider) + { + var annotations = context.Annotations.GetCustomAnnotations (_internalizedKey); + annotations [provider] = _internalizedKey; + } + + public static bool IsInternalized (LinkContext context, IMetadataTokenProvider provider) + { + var annotations = context.Annotations.GetCustomAnnotations (_internalizedKey); + + return annotations.ContainsKey (provider); + } + + private TunerAnnotations () + { + } + } +} From dd79157a009f3f30d3b1a4e61f7f63f1d7d7a48d Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Wed, 25 Sep 2024 20:13:08 +0000 Subject: [PATCH 3/4] Auto-format source code --- .../src/linker/Linker.Steps/BlacklistStep.cs | 2 +- .../src/linker/Linker.Steps/CleanStep.cs | 8 +- .../linker/Linker.Steps/LoadI18nAssemblies.cs | 6 +- .../linker/Linker.Steps/LoadReferencesStep.cs | 2 +- .../src/linker/Linker.Steps/MarkStep.cs | 1081 ++++++++--------- .../src/linker/Linker.Steps/OutputStep.cs | 16 +- .../PreserveDependencyLookupStep.cs | 4 +- .../Linker.Steps/ResolveFromAssemblyStep.cs | 17 +- .../Linker.Steps/ResolveFromXApiStep.cs | 16 +- .../linker/Linker.Steps/ResolveFromXmlStep.cs | 86 +- .../src/linker/Linker.Steps/ResolveStep.cs | 5 +- .../src/linker/Linker.Steps/SweepStep.cs | 45 +- .../src/linker/Linker.Steps/TypeMapStep.cs | 50 +- .../linker/src/linker/Linker/Annotations.cs | 18 +- .../src/linker/Linker/AssemblyResolver.cs | 16 +- .../external/linker/src/linker/Linker/BCL.cs | 21 +- .../linker/src/linker/Linker/ConsoleLogger.cs | 10 +- .../src/linker/Linker/IDependencyRecorder.cs | 8 +- .../linker/src/linker/Linker/ILogger.cs | 13 +- .../Linker/IReflectionPatternRecorder.cs | 8 +- .../linker/src/linker/Linker/Inflater.cs | 103 +- .../linker/src/linker/Linker/KnownMembers.cs | 8 +- .../linker/src/linker/Linker/LinkContext.cs | 52 +- .../linker/src/linker/Linker/LoadException.cs | 8 +- .../LoggingReflectionPatternRecorder.cs | 8 +- .../linker/src/linker/Linker/MarkException.cs | 8 +- .../src/linker/Linker/MarkingHelpers.cs | 2 +- .../src/linker/Linker/MethodBodyScanner.cs | 32 +- .../Linker/MethodDefinitionExtensions.cs | 12 +- .../Linker/MethodReferenceExtensions.cs | 12 +- .../src/linker/Linker/OutputException.cs | 10 +- .../src/linker/Linker/OverrideInformation.cs | 18 +- .../linker/src/linker/Linker/Pipeline.cs | 6 +- .../linker/src/linker/Linker/Tracer.cs | 14 +- .../linker/Linker/TypeDefinitionExtensions.cs | 6 +- .../src/linker/Linker/TypeNameParser.cs | 9 +- .../linker/src/linker/Linker/TypePreserve.cs | 3 +- .../linker/Linker/TypeReferenceExtensions.cs | 48 +- .../linker/src/linker/Linker/XApiReader.cs | 18 +- .../linker/Linker/XmlDependencyRecorder.cs | 34 +- .../Mono.Tuner/ApplyPreserveAttributeBase.cs | 14 +- .../linker/src/tuner/Mono.Tuner/CecilRocks.cs | 32 +- .../src/tuner/Mono.Tuner/CustomizeActions.cs | 4 +- .../linker/src/tuner/Mono.Tuner/Dispatcher.cs | 8 +- .../linker/src/tuner/Mono.Tuner/Extensions.cs | 4 +- .../src/tuner/Mono.Tuner/PreserveCrypto.cs | 10 +- .../Mono.Tuner/PreserveSoapHttpClients.cs | 2 +- .../linker/src/tuner/Mono.Tuner/Profile.cs | 12 +- .../src/tuner/Mono.Tuner/RemoveResources.cs | 8 +- 49 files changed, 939 insertions(+), 998 deletions(-) diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs index f0d2db16676b..6448374c6f06 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/BlacklistStep.cs @@ -86,7 +86,7 @@ bool ShouldProcessAssemblyResource (string name) { AssemblyDefinition assembly = GetAssemblyIfReferenced (name); - if (assembly == null) + if (assembly is null) return false; switch (Annotations.GetAction (assembly)) { diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs index 02713d874245..fd6c1063046d 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/CleanStep.cs @@ -1,4 +1,4 @@ -// +// // CleanStep.cs // // Author: @@ -58,7 +58,7 @@ static void CleanType (TypeDefinition type) static MethodDefinition CheckMethod (TypeDefinition type, MethodDefinition method) { - if (method == null) + if (method is null) return null; return type.Methods.Contains (method) ? method : null; @@ -81,7 +81,7 @@ static void CleanEvents (TypeDefinition type) static bool IsEventUsed (EventDefinition evt) { - return evt.AddMethod != null || evt.InvokeMethod != null || evt.RemoveMethod != null; + return evt.AddMethod is not null || evt.InvokeMethod is not null || evt.RemoveMethod is not null; } static void CleanProperties (TypeDefinition type) @@ -100,7 +100,7 @@ static void CleanProperties (TypeDefinition type) static bool IsPropertyUsed (PropertyDefinition prop) { - return prop.GetMethod != null || prop.SetMethod != null; + return prop.GetMethod is not null || prop.SetMethod is not null; } } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs index cd336a66302f..da8bb3921746 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadI18nAssemblies.cs @@ -34,7 +34,7 @@ namespace Mono.Linker.Steps { public class LoadI18nAssemblies : BaseStep { - static readonly byte [] _pktoken = new byte [] {0x07, 0x38, 0xeb, 0x9f, 0x13, 0x2e, 0xd7, 0x56}; + static readonly byte [] _pktoken = new byte [] { 0x07, 0x38, 0xeb, 0x9f, 0x13, 0x2e, 0xd7, 0x56 }; I18nAssemblies _assemblies; @@ -46,10 +46,10 @@ public LoadI18nAssemblies (I18nAssemblies assemblies) protected override bool ConditionToProcess () { return _assemblies != I18nAssemblies.None && - Context.GetAssemblies ().FirstOrDefault (a => a.Name.Name == "mscorlib")?.MainModule.GetType ("System.MonoType") != null; + Context.GetAssemblies ().FirstOrDefault (a => a.Name.Name == "mscorlib")?.MainModule.GetType ("System.MonoType") is not null; } - protected override void Process() + protected override void Process () { LoadAssembly (GetAssemblyName (I18nAssemblies.Base)); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs index 5cd56d3795dd..06684edb61cb 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/LoadReferencesStep.cs @@ -1,4 +1,4 @@ -// +// // LoadReferencesStep.cs // // Author: diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs index 55bd31187c80..ff46157cbaeb 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/MarkStep.cs @@ -207,34 +207,34 @@ void Process () { while (ProcessPrimaryQueue () || ProcessLazyAttributes () || ProcessLateMarkedAttributes ()) - // deal with [TypeForwardedTo] pseudo-attributes - foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) { - if (!assembly.MainModule.HasExportedTypes) - continue; + // deal with [TypeForwardedTo] pseudo-attributes + foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) { + if (!assembly.MainModule.HasExportedTypes) + continue; - foreach (var exported in assembly.MainModule.ExportedTypes) { - bool isForwarder = exported.IsForwarder; - var declaringType = exported.DeclaringType; - while (!isForwarder && (declaringType != null)) { - isForwarder = declaringType.IsForwarder; - declaringType = declaringType.DeclaringType; - } + foreach (var exported in assembly.MainModule.ExportedTypes) { + bool isForwarder = exported.IsForwarder; + var declaringType = exported.DeclaringType; + while (!isForwarder && (declaringType is not null)) { + isForwarder = declaringType.IsForwarder; + declaringType = declaringType.DeclaringType; + } - if (!isForwarder) - continue; - TypeDefinition type = exported.Resolve (); - if (type == null) - continue; - if (!Annotations.IsMarked (type)) - continue; - Tracer.Push (type); - try { - _context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule); - } finally { - Tracer.Pop (); + if (!isForwarder) + continue; + TypeDefinition type = exported.Resolve (); + if (type is null) + continue; + if (!Annotations.IsMarked (type)) + continue; + Tracer.Push (type); + try { + _context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule); + } finally { + Tracer.Pop (); + } } } - } } bool ProcessPrimaryQueue () @@ -319,7 +319,7 @@ void ProcessPendingBodies () void ProcessVirtualMethod (MethodDefinition method) { var overrides = Annotations.GetOverrides (method); - if (overrides == null) + if (overrides is null) return; foreach (OverrideInformation @override in overrides) @@ -358,7 +358,7 @@ bool IsInterfaceOverrideThatDoesNotNeedMarked (OverrideInformation overrideInfor if (!overrideInformation.IsOverrideOfInterfaceMember || isInstantiated) return false; - if (overrideInformation.MatchingInterfaceImplementation != null) + if (overrideInformation.MatchingInterfaceImplementation is not null) return !Annotations.IsMarked (overrideInformation.MatchingInterfaceImplementation); var interfaceType = overrideInformation.InterfaceType; @@ -368,7 +368,7 @@ bool IsInterfaceOverrideThatDoesNotNeedMarked (OverrideInformation overrideInfor var derivedInterfaceTypes = Annotations.GetDerivedInterfacesForInterface (interfaceType); // There are no derived interface types that could be marked, it's safe to skip marking this override - if (derivedInterfaceTypes == null) + if (derivedInterfaceTypes is null) return true; // If none of the other interfaces on the type that implement the interface from the @base type are marked, then it's safe to skip @@ -482,7 +482,7 @@ protected virtual void MarkUserDependency (MemberReference context, CustomAttrib if (args.Count >= 2 && args [1].Value is string typeName) { td = FindType (assembly ?? context.Module.Assembly, typeName); - if (td == null) { + if (td is null) { _context.LogMessage (MessageImportance.Low, $"Could not resolve '{typeName}' type dependency"); return; } @@ -491,7 +491,7 @@ protected virtual void MarkUserDependency (MemberReference context, CustomAttrib } string member = null; - string[] signature = null; + string [] signature = null; if (args.Count >= 1 && args [0].Value is string memberSignature) { memberSignature = memberSignature.Replace (" ", ""); var sign_start = memberSignature.IndexOf ('('); @@ -527,7 +527,7 @@ static TypeDefinition FindType (AssemblyDefinition assembly, string fullName) return type?.Resolve (); } - bool MarkDependencyMethod (TypeDefinition type, string name, string[] signature) + bool MarkDependencyMethod (TypeDefinition type, string name, string [] signature) { bool marked = false; @@ -537,7 +537,7 @@ bool MarkDependencyMethod (TypeDefinition type, string name, string[] signature) } else { name = name.Substring (0, arity_marker); } - + foreach (var m in type.Methods) { if (m.Name != name) continue; @@ -545,7 +545,7 @@ bool MarkDependencyMethod (TypeDefinition type, string name, string[] signature) if (m.GenericParameters.Count != arity) continue; - if (signature == null) { + if (signature is null) { MarkIndirectlyCalledMethod (m); marked = true; continue; @@ -596,7 +596,7 @@ void LazyMarkCustomAttributes (ICustomAttributeProvider provider, AssemblyDefini protected virtual void MarkCustomAttribute (CustomAttribute ca) { - Tracer.Push ((object)ca.AttributeType ?? (object)ca); + Tracer.Push ((object) ca.AttributeType ?? (object) ca); try { Annotations.Mark (ca); MarkMethod (ca.Constructor); @@ -606,7 +606,7 @@ protected virtual void MarkCustomAttribute (CustomAttribute ca) TypeReference constructor_type = ca.Constructor.DeclaringType; TypeDefinition type = constructor_type.Resolve (); - if (type == null) { + if (type is null) { HandleUnresolvedType (constructor_type); return; } @@ -637,7 +637,7 @@ protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca, ICustomAtt case "System.Runtime.CompilerServices.InternalsVisibleToAttribute": return true; } - + if (!Annotations.IsMarked (attr_type.Resolve ())) return false; } @@ -649,7 +649,7 @@ protected virtual bool ShouldMarkTypeStaticConstructor (TypeDefinition type) { if (Annotations.HasPreservedStaticCtor (type)) return false; - + if (type.IsBeforeFieldInit && _context.IsOptimizationEnabled (CodeOptimizations.BeforeFieldInit)) return false; @@ -658,7 +658,7 @@ protected virtual bool ShouldMarkTypeStaticConstructor (TypeDefinition type) protected void MarkStaticConstructor (TypeDefinition type) { - if (MarkMethodIf (type.Methods, IsNonEmptyStaticConstructor) != null) + if (MarkMethodIf (type.Methods, IsNonEmptyStaticConstructor) is not null) Annotations.SetPreservedStaticCtor (type); } @@ -680,11 +680,11 @@ protected virtual bool ShouldMarkTopLevelCustomAttribute (AttributeProviderPair string attributeName = ca.Constructor.DeclaringType.Name; if (attributeName == "DebuggerDisplayAttribute" || attributeName == "DebuggerTypeProxyAttribute") { var displayTargetType = GetDebuggerAttributeTargetType (app.Attribute, (AssemblyDefinition) app.Provider); - if (displayTargetType == null || !Annotations.IsMarked (displayTargetType)) + if (displayTargetType is null || !Annotations.IsMarked (displayTargetType)) return false; - } + } } - + return true; } @@ -692,7 +692,7 @@ protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider) { // most security declarations are removed (if linked) but user code might still have some // and if the attributes references types then they need to be marked too - if ((provider == null) || !provider.HasSecurityDeclarations) + if ((provider is null) || !provider.HasSecurityDeclarations) return; foreach (var sd in provider.SecurityDeclarations) @@ -703,7 +703,7 @@ protected virtual void MarkSecurityDeclaration (SecurityDeclaration sd) { if (!sd.HasSecurityAttributes) return; - + foreach (var sa in sd.SecurityAttributes) MarkSecurityAttribute (sa); } @@ -712,11 +712,11 @@ protected virtual void MarkSecurityAttribute (SecurityAttribute sa) { TypeReference security_type = sa.AttributeType; TypeDefinition type = security_type.Resolve (); - if (type == null) { + if (type is null) { HandleUnresolvedType (security_type); return; } - + MarkType (security_type); MarkSecurityAttributeProperties (sa, type); MarkSecurityAttributeFields (sa, type); @@ -753,7 +753,7 @@ protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedAr { PropertyDefinition property = GetProperty (attribute, namedArgument.Name); Tracer.Push (property); - if (property != null) + if (property is not null) MarkMethod (property.SetMethod); MarkCustomAttributeArgument (namedArgument.Argument); @@ -762,9 +762,9 @@ protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedAr PropertyDefinition GetProperty (TypeDefinition type, string propertyname) { - while (type != null) { + while (type is not null) { PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname); - if (property != null) + if (property is not null) return property; type = type.BaseType?.Resolve (); @@ -785,7 +785,7 @@ protected void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition att protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute) { FieldDefinition field = GetField (attribute, namedArgument.Name); - if (field != null) + if (field is not null) MarkField (field); MarkCustomAttributeArgument (namedArgument.Argument); @@ -793,9 +793,9 @@ protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgum FieldDefinition GetField (TypeDefinition type, string fieldname) { - while (type != null) { + while (type is not null) { FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname); - if (field != null) + if (field is not null) return field; type = type.BaseType?.Resolve (); @@ -806,9 +806,9 @@ FieldDefinition GetField (TypeDefinition type, string fieldname) MethodDefinition GetMethodWithNoParameters (TypeDefinition type, string methodname) { - while (type != null) { + while (type is not null) { MethodDefinition method = type.Methods.FirstOrDefault (m => m.Name == methodname && !m.HasParameters); - if (method != null) + if (method is not null) return method; type = type.BaseType.Resolve (); @@ -834,10 +834,10 @@ void MarkCustomAttributeArgument (CustomAttributeArgument argument) var et = at.GetElementType (); MarkType (et); - if (argument.Value == null) + if (argument.Value is null) return; - foreach (var caa in (CustomAttributeArgument [])argument.Value) + foreach (var caa in (CustomAttributeArgument []) argument.Value) MarkCustomAttributeArgument (caa); return; @@ -847,11 +847,11 @@ void MarkCustomAttributeArgument (CustomAttributeArgument argument) switch (at.Name) { case "Type": MarkType (argument.Type); - MarkType ((TypeReference)argument.Value); + MarkType ((TypeReference) argument.Value); return; case "Object": - var boxed_value = (CustomAttributeArgument)argument.Value; + var boxed_value = (CustomAttributeArgument) argument.Value; MarkType (boxed_value.Type); MarkCustomAttributeArgument (boxed_value); return; @@ -900,10 +900,8 @@ void ProcessModule (AssemblyDefinition assembly) { // Pre-mark if there is any methods as they need to be executed // at assembly load time - foreach (TypeDefinition type in assembly.MainModule.Types) - { - if (type.Name == "" && type.HasMethods) - { + foreach (TypeDefinition type in assembly.MainModule.Types) { + if (type.Name == "" && type.HasMethods) { MarkType (type); break; } @@ -927,7 +925,7 @@ bool ProcessLazyAttributes () var customAttribute = assemblyLevelAttribute.Attribute; var resolved = customAttribute.Constructor.Resolve (); - if (resolved == null) { + if (resolved is null) { HandleUnresolvedMethod (customAttribute.Constructor); continue; } @@ -972,7 +970,7 @@ bool ProcessLateMarkedAttributes () var customAttribute = attributeProviderPair.Attribute; var resolved = customAttribute.Constructor.Resolve (); - if (resolved == null) { + if (resolved is null) { HandleUnresolvedMethod (customAttribute.Constructor); continue; } @@ -1001,7 +999,7 @@ protected void MarkField (FieldReference reference) FieldDefinition field = reference.Resolve (); - if (field == null) { + if (field is null) { HandleUnresolvedField (reference); return; } @@ -1052,7 +1050,7 @@ protected virtual void MarkSerializable (TypeDefinition type) protected virtual TypeDefinition MarkType (TypeReference reference) { - if (reference == null) + if (reference is null) return null; reference = GetOriginalType (reference); @@ -1063,12 +1061,12 @@ protected virtual TypeDefinition MarkType (TypeReference reference) if (reference is GenericParameter) return null; -// if (IgnoreScope (reference.Scope)) -// return null; + // if (IgnoreScope (reference.Scope)) + // return null; TypeDefinition type = reference.Resolve (); - if (type == null) { + if (type is null) { HandleUnresolvedType (reference); return null; } @@ -1159,7 +1157,7 @@ protected virtual void DoAdditionalProcessing () protected virtual void DoAdditionalTypeProcessing (TypeDefinition type) { } - + // Allow subclassers to mark additional things protected virtual void DoAdditionalFieldProcessing (FieldDefinition field) { @@ -1211,7 +1209,7 @@ TypeDefinition GetDebuggerAttributeTargetType (CustomAttribute ca, AssemblyDefin return targetTypeReference?.Resolve (); } - + void MarkTypeSpecialCustomAttributes (TypeDefinition type) { if (!type.HasCustomAttributes) @@ -1291,7 +1289,7 @@ protected virtual void MarkTypeConverterLikeDependency (CustomAttribute attribut break; } - if (tdef == null) + if (tdef is null) return; MarkMethodsIf (tdef.Methods, predicate); @@ -1301,7 +1299,7 @@ void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute { if (_context.KeepMembersForDebugger) { - string displayString = (string) attribute.ConstructorArguments[0].Value; + string displayString = (string) attribute.ConstructorArguments [0].Value; Regex regex = new Regex ("{[^{}]+}", RegexOptions.Compiled); @@ -1311,37 +1309,37 @@ void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute // Remove ",nq" suffix if present // (it asks the expression evaluator to remove the quotes when displaying the final value) - if (Regex.IsMatch(realMatch, @".+,\s*nq")) { + if (Regex.IsMatch (realMatch, @".+,\s*nq")) { realMatch = realMatch.Substring (0, realMatch.LastIndexOf (',')); } if (realMatch.EndsWith ("()")) { string methodName = realMatch.Substring (0, realMatch.Length - 2); MethodDefinition method = GetMethodWithNoParameters (type, methodName); - if (method != null) { + if (method is not null) { MarkMethod (method); continue; } } else { FieldDefinition field = GetField (type, realMatch); - if (field != null) { + if (field is not null) { MarkField (field); continue; } PropertyDefinition property = GetProperty (type, realMatch); - if (property != null) { - if (property.GetMethod != null) { + if (property is not null) { + if (property.GetMethod is not null) { MarkMethod (property.GetMethod); } - if (property.SetMethod != null) { + if (property.SetMethod is not null) { MarkMethod (property.SetMethod); } continue; } } - while (type != null) { + while (type is not null) { MarkMethods (type); MarkFields (type, includeStatic: true); type = type.BaseType?.Resolve (); @@ -1354,22 +1352,22 @@ void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute) { if (_context.KeepMembersForDebugger) { - object constructorArgument = attribute.ConstructorArguments[0].Value; + object constructorArgument = attribute.ConstructorArguments [0].Value; TypeReference proxyTypeReference = constructorArgument as TypeReference; - if (proxyTypeReference == null) { + if (proxyTypeReference is null) { if (constructorArgument is string proxyTypeReferenceString) { proxyTypeReference = type.Module.GetType (proxyTypeReferenceString, runtimeName: true); } } - if (proxyTypeReference == null) { + if (proxyTypeReference is null) { return; } MarkType (proxyTypeReference); TypeDefinition proxyType = proxyTypeReference.Resolve (); - if (proxyType != null) { + if (proxyType is not null) { MarkMethods (proxyType); MarkFields (proxyType, includeStatic: true); } @@ -1385,7 +1383,7 @@ static bool TryGetStringArgument (CustomAttribute attribute, out string argument argument = attribute.ConstructorArguments [0].Value as string; - return argument != null; + return argument is not null; } protected int MarkNamedMethod (TypeDefinition type, string method_name) @@ -1452,11 +1450,11 @@ void MarkInterfaceImplementations (TypeDefinition type) // Only mark interface implementations of interface types that have been marked. // This enables stripping of interfaces that are never used var resolvedInterfaceType = iface.InterfaceType.Resolve (); - if (resolvedInterfaceType == null) { + if (resolvedInterfaceType is null) { HandleUnresolvedType (iface.InterfaceType); continue; } - + if (ShouldMarkInterfaceImplementation (type, iface, resolvedInterfaceType)) MarkInterfaceImplementation (iface); } @@ -1489,7 +1487,7 @@ bool IsVirtualNeededByTypeDueToPreservedScope (MethodDefinition method) return false; var base_list = Annotations.GetBaseMethods (method); - if (base_list == null) + if (base_list is null) return false; foreach (MethodDefinition @base in base_list) { @@ -1497,7 +1495,7 @@ bool IsVirtualNeededByTypeDueToPreservedScope (MethodDefinition method) // if the type is never instantiated, interfaces will be removed if (@base.DeclaringType.IsInterface) continue; - + // If the type is marked, we need to keep overrides of abstract members defined in assemblies // that are copied. However, if the base method is virtual, then we don't need to keep the override // until the type could be instantiated @@ -1513,14 +1511,14 @@ bool IsVirtualNeededByTypeDueToPreservedScope (MethodDefinition method) return false; } - + bool IsVirtualNeededByInstantiatedTypeDueToPreservedScope (MethodDefinition method) { if (!method.IsVirtual) return false; var base_list = Annotations.GetBaseMethods (method); - if (base_list == null) + if (base_list is null) return false; foreach (MethodDefinition @base in base_list) { @@ -1570,7 +1568,7 @@ protected bool MarkDefaultConstructor (TypeDefinition type) if (type?.HasMethods != true) return false; - return MarkMethodIf (type.Methods, MethodDefinitionExtensions.IsDefaultConstructor) != null; + return MarkMethodIf (type.Methods, MethodDefinitionExtensions.IsDefaultConstructor) is not null; } static bool IsNonEmptyStaticConstructor (MethodDefinition method) @@ -1609,14 +1607,14 @@ static bool HasSerializationAttribute (MethodDefinition method) protected virtual bool AlwaysMarkTypeAsInstantiated (TypeDefinition td) { switch (td.Name) { - // These types are created from native code which means we are unable to track when they are instantiated - // Since these are such foundational types, let's take the easy route and just always assume an instance of one of these - // could exist - case "Delegate": - case "MulticastDelegate": - case "ValueType": - case "Enum": - return td.Namespace == "System"; + // These types are created from native code which means we are unable to track when they are instantiated + // Since these are such foundational types, let's take the easy route and just always assume an instance of one of these + // could exist + case "Delegate": + case "MulticastDelegate": + case "ValueType": + case "Enum": + return td.Namespace == "System"; } return false; @@ -1641,11 +1639,11 @@ TypeDefinition ResolveFullyQualifiedTypeName (string name) return null; foreach (var assemblyDefinition in _context.GetAssemblies ()) { - if (assemblyName != null && assemblyDefinition.Name.Name != assemblyName) + if (assemblyName is not null && assemblyDefinition.Name.Name != assemblyName) continue; var foundType = assemblyDefinition.MainModule.GetType (typeName); - if (foundType == null) + if (foundType is null) continue; return foundType; @@ -1669,7 +1667,7 @@ protected TypeReference GetOriginalType (TypeReference type) break; // FunctionPointerType is the original type } - type = ((TypeSpecification)type).ElementType; + type = ((TypeSpecification) type).ElementType; } return type; @@ -1680,9 +1678,8 @@ void MarkParameters (FunctionPointerType fnptr) if (!fnptr.HasParameters) return; - for (int i = 0; i < fnptr.Parameters.Count; i++) - { - MarkType (fnptr.Parameters[i].ParameterType); + for (int i = 0; i < fnptr.Parameters.Count; i++) { + MarkType (fnptr.Parameters [i].ParameterType); } } @@ -1704,7 +1701,7 @@ void MarkGenericArgumentConstructors (IGenericInstance instance) var arguments = instance.GenericArguments; var generic_element = GetGenericProviderFromInstance (instance); - if (generic_element == null) + if (generic_element is null) return; var parameters = generic_element.GenericParameters; @@ -1761,7 +1758,7 @@ void ApplyPreserveInfo (TypeDefinition type) void ApplyPreserveMethods (TypeDefinition type) { var list = Annotations.GetPreservedMethods (type); - if (list == null) + if (list is null) return; MarkMethodCollection (list); @@ -1770,7 +1767,7 @@ void ApplyPreserveMethods (TypeDefinition type) void ApplyPreserveMethods (MethodDefinition method) { var list = Annotations.GetPreservedMethods (method); - if (list == null) + if (list is null) return; MarkMethodCollection (list); @@ -1794,7 +1791,7 @@ protected bool MarkFields (TypeDefinition type, bool includeStatic, bool markBac // // instead we will search the properties and find the one that makes use of the current backing field var propertyDefinition = SearchPropertiesForMatchingFieldDefinition (field); - if (propertyDefinition != null && !Annotations.IsMarked (propertyDefinition)) + if (propertyDefinition is not null && !Annotations.IsMarked (propertyDefinition)) continue; } MarkField (field); @@ -1807,7 +1804,7 @@ static PropertyDefinition SearchPropertiesForMatchingFieldDefinition (FieldDefin { foreach (var property in field.DeclaringType.Properties) { var instr = property.GetMethod?.Body?.Instructions; - if (instr == null) + if (instr is null) continue; foreach (var ins in instr) { @@ -1862,13 +1859,13 @@ protected virtual MethodDefinition MarkMethod (MethodReference reference) if (reference.DeclaringType is GenericInstanceType) MarkType (reference.DeclaringType); -// if (IgnoreScope (reference.DeclaringType.Scope)) -// return; + // if (IgnoreScope (reference.DeclaringType.Scope)) + // return; MethodDefinition method = reference.Resolve (); try { - if (method == null) { + if (method is null) { HandleUnresolvedMethod (reference); return null; } @@ -2023,8 +2020,8 @@ protected virtual IEnumerable GetRequiredMethodsForInstantiate void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReference ov) { var resolvedOverride = ov.Resolve (); - - if (resolvedOverride == null) { + + if (resolvedOverride is null) { HandleUnresolvedMethod (ov); return; } @@ -2032,7 +2029,7 @@ void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReferen if (resolvedOverride.DeclaringType.IsInterface) { foreach (var ifaceImpl in method.DeclaringType.Interfaces) { var resolvedInterfaceType = ifaceImpl.InterfaceType.Resolve (); - if (resolvedInterfaceType == null) { + if (resolvedInterfaceType is null) { HandleUnresolvedType (ifaceImpl.InterfaceType); continue; } @@ -2066,29 +2063,29 @@ void MarkNewCodeDependencies (MethodDefinition method) protected virtual void MarkAndCacheConvertToThrowExceptionCtor () { - if (_context.MarkedKnownMembers.NotSupportedExceptionCtorString != null) + if (_context.MarkedKnownMembers.NotSupportedExceptionCtorString is not null) return; var nse = BCL.FindPredefinedType ("System", "NotSupportedException", _context); - if (nse == null) + if (nse is null) throw new NotSupportedException ("Missing predefined 'System.NotSupportedException' type"); MarkType (nse); var nseCtor = MarkMethodIf (nse.Methods, KnownMembers.IsNotSupportedExceptionCtorString); - if (nseCtor == null) + if (nseCtor is null) throw new MarkException ($"Could not find constructor on '{nse.FullName}'"); _context.MarkedKnownMembers.NotSupportedExceptionCtorString = nseCtor; var objectType = BCL.FindPredefinedType ("System", "Object", _context); - if (objectType == null) + if (objectType is null) throw new NotSupportedException ("Missing predefined 'System.Object' type"); MarkType (objectType); var objectCtor = MarkMethodIf (objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor); - if (objectCtor == null) + if (objectCtor is null) throw new MarkException ($"Could not find constructor on '{objectType.FullName}'"); _context.MarkedKnownMembers.ObjectCtor = objectCtor; @@ -2096,17 +2093,17 @@ protected virtual void MarkAndCacheConvertToThrowExceptionCtor () bool MarkDisablePrivateReflectionAttribute () { - if (_context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor != null) + if (_context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor is not null) return false; var nse = BCL.FindPredefinedType ("System.Runtime.CompilerServices", "DisablePrivateReflectionAttribute", _context); - if (nse == null) + if (nse is null) throw new NotSupportedException ("Missing predefined 'System.Runtime.CompilerServices.DisablePrivateReflectionAttribute' type"); MarkType (nse); var ctor = MarkMethodIf (nse.Methods, MethodDefinitionExtensions.IsDefaultConstructor); - if (ctor == null) + if (ctor is null) throw new MarkException ($"Could not find constructor on '{nse.FullName}'"); _context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor; @@ -2116,7 +2113,7 @@ bool MarkDisablePrivateReflectionAttribute () void MarkBaseMethods (MethodDefinition method) { var base_methods = Annotations.GetBaseMethods (method); - if (base_methods == null) + if (base_methods is null) return; foreach (MethodDefinition base_method in base_methods) { @@ -2128,12 +2125,12 @@ void MarkBaseMethods (MethodDefinition method) } } - void ProcessInteropMethod(MethodDefinition method) + void ProcessInteropMethod (MethodDefinition method) { TypeDefinition returnTypeDefinition = method.ReturnType.Resolve (); const bool includeStaticFields = false; - if (returnTypeDefinition != null && !returnTypeDefinition.IsImport) { + if (returnTypeDefinition is not null && !returnTypeDefinition.IsImport) { MarkDefaultConstructor (returnTypeDefinition); MarkFields (returnTypeDefinition, includeStaticFields); } @@ -2148,7 +2145,7 @@ void ProcessInteropMethod(MethodDefinition method) paramTypeReference = (paramTypeReference as TypeSpecification).ElementType; } TypeDefinition paramTypeDefinition = paramTypeReference.Resolve (); - if (paramTypeDefinition != null && !paramTypeDefinition.IsImport) { + if (paramTypeDefinition is not null && !paramTypeDefinition.IsImport) { MarkFields (paramTypeDefinition, includeStaticFields); if (pd.ParameterType.IsByReference) { MarkDefaultConstructor (paramTypeDefinition); @@ -2199,7 +2196,7 @@ protected virtual void MarkEvent (EventDefinition evt) void MarkMethodIfNotNull (MethodReference method) { - if (method == null) + if (method is null) return; MarkMethod (method); @@ -2236,7 +2233,7 @@ bool IsUnreachableBody (MethodBody body) && !Annotations.IsInstantiated (body.Method.DeclaringType) && MethodBodyScanner.IsWorthConvertingToThrow (body); } - + partial void PostMarkMethodBody (MethodBody body); @@ -2246,7 +2243,7 @@ void MarkInterfacesNeededByBodyStack (MethodBody body) // then we need to mark that interface implementation. When this occurs it is not safe to remove the interface implementation from the type // even if the type is never instantiated var implementations = MethodBodyScanner.GetReferencedInterfaces (_context.Annotations, body); - if (implementations == null) + if (implementations is null) return; foreach (var implementation in implementations) @@ -2366,14 +2363,13 @@ protected virtual void MarkReflectionLikeDependencies (MethodBody body) continue; var methodCalledDefinition = methodCalled.Resolve (); - if (methodCalledDefinition == null) + if (methodCalledDefinition is null) continue; ReflectionPatternContext reflectionContext = new ReflectionPatternContext (_context, body.Method, methodCalledDefinition, i); try { detector.Process (ref reflectionContext); - } - finally { + } finally { reflectionContext.Dispose (); } } @@ -2387,8 +2383,7 @@ protected virtual void MarkReflectionLikeDependencies (MethodBody body) /// The promise of the pattern recorder is that for a given reflection method, it will either not talk /// about it ever, or it will always report recognized/unrecognized. /// - struct ReflectionPatternContext : IDisposable - { + struct ReflectionPatternContext : IDisposable { readonly LinkContext _context; #if DEBUG bool _patternAnalysisAttempted; @@ -2412,7 +2407,7 @@ public ReflectionPatternContext (LinkContext context, MethodDefinition methodCal #endif } - [Conditional("DEBUG")] + [Conditional ("DEBUG")] public void AnalyzingPattern () { #if DEBUG @@ -2450,13 +2445,12 @@ public void RecordUnrecognizedPattern (string message) public void Dispose () { #if DEBUG - Debug.Assert(!_patternAnalysisAttempted || _patternReported, "A reflection pattern was analyzed, but no result was reported."); + Debug.Assert (!_patternAnalysisAttempted || _patternReported, "A reflection pattern was analyzed, but no result was reported."); #endif } } - class ReflectionPatternDetector - { + class ReflectionPatternDetector { readonly MarkStep _markStep; readonly MethodDefinition _methodCalling; readonly Collection _instructions; @@ -2475,441 +2469,441 @@ public void Process (ref ReflectionPatternContext reflectionContext) var methodCalledType = methodCalled.DeclaringType; switch (methodCalledType.Name) { + // + // System.Type + // + case "Type" when methodCalledType.Namespace == "System": + + // Some of the overloads are implemented by calling another overload of the same name. + // These "internal" calls are not interesting to analyze, the outermost call is the one + // which needs to be analyzed. The assumption is that all overloads have the same semantics. + // (for example that all overload of GetConstructor if used require the specified type to have a .ctor). + if (_methodCalling.DeclaringType == methodCalled.DeclaringType && _methodCalling.Name == methodCalled.Name) + break; + + switch (methodCalled.Name) { // - // System.Type + // GetConstructor (Type []) + // GetConstructor (BindingFlags, Binder, Type [], ParameterModifier []) + // GetConstructor (BindingFlags, Binder, CallingConventions, Type [], ParameterModifier []) // - case "Type" when methodCalledType.Namespace == "System": + case "GetConstructor": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Constructor, instructionIndex - 1); - // Some of the overloads are implemented by calling another overload of the same name. - // These "internal" calls are not interesting to analyze, the outermost call is the one - // which needs to be analyzed. The assumption is that all overloads have the same semantics. - // (for example that all overload of GetConstructor if used require the specified type to have a .ctor). - if (_methodCalling.DeclaringType == methodCalled.DeclaringType && _methodCalling.Name == methodCalled.Name) - break; + break; - switch (methodCalled.Name) { - // - // GetConstructor (Type []) - // GetConstructor (BindingFlags, Binder, Type [], ParameterModifier []) - // GetConstructor (BindingFlags, Binder, CallingConventions, Type [], ParameterModifier []) - // - case "GetConstructor": - if (!methodCalled.IsStatic) - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Constructor, instructionIndex - 1); + // + // GetMethod (string) + // GetMethod (string, BindingFlags) + // GetMethod (string, Type[]) + // GetMethod (string, Type[], ParameterModifier[]) + // GetMethod (string, BindingFlags, Binder, Type[], ParameterModifier[]) + // GetMethod (string, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[]) + // + // TODO: .NET Core extensions + // GetMethod (string, int, Type[]) + // GetMethod (string, int, Type[], ParameterModifier[]?) + // GetMethod (string, int, BindingFlags, Binder?, Type[], ParameterModifier[]?) + // GetMethod (string, int, BindingFlags, Binder?, CallingConventions, Type[], ParameterModifier[]?) + // + case "GetMethod": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1); - break; + break; - // - // GetMethod (string) - // GetMethod (string, BindingFlags) - // GetMethod (string, Type[]) - // GetMethod (string, Type[], ParameterModifier[]) - // GetMethod (string, BindingFlags, Binder, Type[], ParameterModifier[]) - // GetMethod (string, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[]) - // - // TODO: .NET Core extensions - // GetMethod (string, int, Type[]) - // GetMethod (string, int, Type[], ParameterModifier[]?) - // GetMethod (string, int, BindingFlags, Binder?, Type[], ParameterModifier[]?) - // GetMethod (string, int, BindingFlags, Binder?, CallingConventions, Type[], ParameterModifier[]?) - // - case "GetMethod": - if (!methodCalled.IsStatic) - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1); + // + // GetField (string) + // GetField (string, BindingFlags) + // + case "GetField": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1); - break; + break; - // - // GetField (string) - // GetField (string, BindingFlags) - // - case "GetField": - if (!methodCalled.IsStatic) - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1); + // + // GetEvent (string) + // GetEvent (string, BindingFlags) + // + case "GetEvent": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1); - break; + break; - // - // GetEvent (string) - // GetEvent (string, BindingFlags) - // - case "GetEvent": - if (!methodCalled.IsStatic) - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1); + // + // GetProperty (string) + // GetProperty (string, BindingFlags) + // GetProperty (string, Type) + // GetProperty (string, Type[]) + // GetProperty (string, Type, Type[]) + // GetProperty (string, Type, Type[], ParameterModifier[]) + // GetProperty (string, BindingFlags, Binder, Type, Type[], ParameterModifier[]) + // + case "GetProperty": + if (!methodCalled.IsStatic) + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1); - break; + break; - // - // GetProperty (string) - // GetProperty (string, BindingFlags) - // GetProperty (string, Type) - // GetProperty (string, Type[]) - // GetProperty (string, Type, Type[]) - // GetProperty (string, Type, Type[], ParameterModifier[]) - // GetProperty (string, BindingFlags, Binder, Type, Type[], ParameterModifier[]) - // - case "GetProperty": - if (!methodCalled.IsStatic) - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1); + // + // GetType (string) + // GetType (string, Boolean) + // GetType (string, Boolean, Boolean) + // GetType (string, Func, Func) + // GetType (string, Func, Func, Boolean) + // GetType (string, Func, Func, Boolean, Boolean) + // + case "GetType": + if (!methodCalled.IsStatic) { + break; + } else { + reflectionContext.AnalyzingPattern (); + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); break; + } // - // GetType (string) - // GetType (string, Boolean) - // GetType (string, Boolean, Boolean) - // GetType (string, Func, Func) - // GetType (string, Func, Func, Boolean) - // GetType (string, Func, Func, Boolean, Boolean) + // The next value must be string constant (we don't handle anything else) // - case "GetType": - if (!methodCalled.IsStatic) { - break; - } else { - reflectionContext.AnalyzingPattern (); - - var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); - if (first_arg_instr < 0) { - reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); - break; - } - - // - // The next value must be string constant (we don't handle anything else) - // - var first_arg = _instructions [first_arg_instr]; - if (first_arg.OpCode != OpCodes.Ldstr) { - reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with argument which cannot be analyzed"); - break; - } - - string typeName = (string)first_arg.Operand; - TypeDefinition foundType = _markStep.ResolveFullyQualifiedTypeName (typeName); - if (foundType == null) { - reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with type name `{typeName}` which can't be resolved."); - break; - } - - reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkType (foundType)); - } + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with argument which cannot be analyzed"); break; + } + + string typeName = (string) first_arg.Operand; + TypeDefinition foundType = _markStep.ResolveFullyQualifiedTypeName (typeName); + if (foundType is null) { + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with type name `{typeName}` which can't be resolved."); + break; + } + + reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkType (foundType)); } + break; + } + + break; + + // + // System.Linq.Expressions.Expression + // + case "Expression" when methodCalledType.Namespace == "System.Linq.Expressions": + Instruction second_argument; + TypeDefinition declaringType; + if (!methodCalled.IsStatic) break; + switch (methodCalled.Name) { + // - // System.Linq.Expressions.Expression + // static Call (Type, String, Type[], Expression[]) // - case "Expression" when methodCalledType.Namespace == "System.Linq.Expressions": - Instruction second_argument; - TypeDefinition declaringType; + case "Call": { + reflectionContext.AnalyzingPattern (); - if (!methodCalled.IsStatic) + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 4); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); break; + } - switch (methodCalled.Name) { + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldtoken) + first_arg_instr++; - // - // static Call (Type, String, Type[], Expression[]) - // - case "Call": { - reflectionContext.AnalyzingPattern (); - - var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 4); - if (first_arg_instr < 0) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); - break; - } - - var first_arg = _instructions [first_arg_instr]; - if (first_arg.OpCode == OpCodes.Ldtoken) - first_arg_instr++; - - declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); - if (declaringType == null) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); - break; - } - - var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); - second_argument = _instructions [second_arg_instr]; - if (second_argument.OpCode != OpCodes.Ldstr) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); - break; - } - - var name = (string)second_argument.Operand; - - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, null, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - } + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); + if (declaringType is null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); + break; + } - break; + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); + second_argument = _instructions [second_arg_instr]; + if (second_argument.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); + break; + } - // - // static Property(Expression, Type, String) - // static Field (Expression, Type, String) - // - case "Property": - case "Field": { - reflectionContext.AnalyzingPattern (); - - var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 2); - if (second_arg_instr < 0) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); - break; - } - - var second_arg = _instructions [second_arg_instr]; - if (second_arg.OpCode == OpCodes.Ldtoken) - second_arg_instr++; - - declaringType = FindReflectionTypeForLookup (_instructions, second_arg_instr); - if (declaringType == null) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); - break; - } - - var third_arg_inst = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); - var third_argument = _instructions [third_arg_inst]; - if (third_argument.OpCode != OpCodes.Ldstr) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with the 3rd argument which cannot be analyzed"); - break; - } - - var name = (string)third_argument.Operand; - - // - // The first argument can be any expression but we are looking only for simple null - // which we can convert to static only field lookup - // - var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); - bool staticOnly = false; - - if (first_arg_instr >= 0) { - var first_arg = _instructions [first_arg_instr]; - if (first_arg.OpCode == OpCodes.Ldnull) - staticOnly = true; - } - - if (methodCalled.Name [0] == 'P') - MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); - else - MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); - } + var name = (string) second_argument.Operand; - break; + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, null, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } - // - // static New (Type) - // - case "New": { - reflectionContext.AnalyzingPattern (); - - var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); - if (first_arg_instr < 0) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); - break; - } - - var first_arg = _instructions [first_arg_instr]; - if (first_arg.OpCode == OpCodes.Ldtoken) - first_arg_instr++; - - declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); - if (declaringType == null) { - reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); - break; - } - - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, BindingFlags.Instance, parametersCount: 0); - } - break; + break; + + // + // static Property(Expression, Type, String) + // static Field (Expression, Type, String) + // + case "Property": + case "Field": { + reflectionContext.AnalyzingPattern (); + + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 2); + if (second_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; } - break; + var second_arg = _instructions [second_arg_instr]; + if (second_arg.OpCode == OpCodes.Ldtoken) + second_arg_instr++; + + declaringType = FindReflectionTypeForLookup (_instructions, second_arg_instr); + if (declaringType is null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 2nd argument which cannot be analyzed"); + break; + } + + var third_arg_inst = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); + var third_argument = _instructions [third_arg_inst]; + if (third_argument.OpCode != OpCodes.Ldstr) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with the 3rd argument which cannot be analyzed"); + break; + } + + var name = (string) third_argument.Operand; + + // + // The first argument can be any expression but we are looking only for simple null + // which we can convert to static only field lookup + // + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 3); + bool staticOnly = false; + + if (first_arg_instr >= 0) { + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldnull) + staticOnly = true; + } + + if (methodCalled.Name [0] == 'P') + MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); + else + MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name, staticOnly); + } + + break; // - // System.Reflection.RuntimeReflectionExtensions + // static New (Type) // - case "RuntimeReflectionExtensions" when methodCalledType.Namespace == "System.Reflection": - switch (methodCalled.Name) { - // - // static GetRuntimeField (this Type type, string name) - // - case "GetRuntimeField": - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1, thisExtension: true); - break; + case "New": { + reflectionContext.AnalyzingPattern (); - // - // static GetRuntimeMethod (this Type type, string name, Type[] parameters) - // - case "GetRuntimeMethod": - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1, thisExtension: true); - break; + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, 1); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } - // - // static GetRuntimeProperty (this Type type, string name) - // - case "GetRuntimeProperty": - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1, thisExtension: true); - break; + var first_arg = _instructions [first_arg_instr]; + if (first_arg.OpCode == OpCodes.Ldtoken) + first_arg_instr++; - // - // static GetRuntimeEvent (this Type type, string name) - // - case "GetRuntimeEvent": - ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1, thisExtension: true); - break; + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr); + if (declaringType is null) { + reflectionContext.RecordUnrecognizedPattern ($"Expression call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument which cannot be analyzed"); + break; } + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, BindingFlags.Instance, parametersCount: 0); + } + break; + } + + break; + + // + // System.Reflection.RuntimeReflectionExtensions + // + case "RuntimeReflectionExtensions" when methodCalledType.Namespace == "System.Reflection": + switch (methodCalled.Name) { + // + // static GetRuntimeField (this Type type, string name) + // + case "GetRuntimeField": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Field, instructionIndex - 1, thisExtension: true); + break; + + // + // static GetRuntimeMethod (this Type type, string name, Type[] parameters) + // + case "GetRuntimeMethod": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Method, instructionIndex - 1, thisExtension: true); break; // - // System.AppDomain + // static GetRuntimeProperty (this Type type, string name) // - case "AppDomain" when methodCalledType.Namespace == "System": - // - // CreateInstance (string assemblyName, string typeName) - // CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) - // CreateInstance (string assemblyName, string typeName, object? []? activationAttributes) - // - // CreateInstanceAndUnwrap (string assemblyName, string typeName) - // CreateInstanceAndUnwrap (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) - // CreateInstanceAndUnwrap (string assemblyName, string typeName, object? []? activationAttributes) - // - // CreateInstanceFrom (string assemblyFile, string typeName) - // CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) - // CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) - // - // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName) - // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) - // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, object? []? activationAttributes) - // - switch (methodCalled.Name) { - case "CreateInstance": - case "CreateInstanceAndUnwrap": - case "CreateInstanceFrom": - case "CreateInstanceFromAndUnwrap": - ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); - break; - } + case "GetRuntimeProperty": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Property, instructionIndex - 1, thisExtension: true); + break; + // + // static GetRuntimeEvent (this Type type, string name) + // + case "GetRuntimeEvent": + ProcessSystemTypeGetMemberLikeCall (ref reflectionContext, System.Reflection.MemberTypes.Event, instructionIndex - 1, thisExtension: true); break; + } + + break; + // + // System.AppDomain + // + case "AppDomain" when methodCalledType.Namespace == "System": + // + // CreateInstance (string assemblyName, string typeName) + // CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstance (string assemblyName, string typeName, object? []? activationAttributes) + // + // CreateInstanceAndUnwrap (string assemblyName, string typeName) + // CreateInstanceAndUnwrap (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceAndUnwrap (string assemblyName, string typeName, object? []? activationAttributes) + // + // CreateInstanceFrom (string assemblyFile, string typeName) + // CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) // - // System.Reflection.Assembly + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName) + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // CreateInstanceFromAndUnwrap (string assemblyFile, string typeName, object? []? activationAttributes) + // + switch (methodCalled.Name) { + case "CreateInstance": + case "CreateInstanceAndUnwrap": + case "CreateInstanceFrom": + case "CreateInstanceFromAndUnwrap": + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); + break; + } + + break; + + // + // System.Reflection.Assembly + // + case "Assembly" when methodCalledType.Namespace == "System.Reflection": // - case "Assembly" when methodCalledType.Namespace == "System.Reflection": + // CreateInstance (string typeName) + // CreateInstance (string typeName, bool ignoreCase) + // CreateInstance (string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object []? args, CultureInfo? culture, object []? activationAttributes) + // + if (methodCalled.Name == "CreateInstance") { // - // CreateInstance (string typeName) - // CreateInstance (string typeName, bool ignoreCase) - // CreateInstance (string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object []? args, CultureInfo? culture, object []? activationAttributes) + // TODO: This could be supported for `this` only calls // - if (methodCalled.Name == "CreateInstance") { - // - // TODO: This could be supported for `this` only calls - // - reflectionContext.AnalyzingPattern (); - reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not yet supported"); - break; - } + reflectionContext.AnalyzingPattern (); + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not yet supported"); + break; + } + break; + + // + // System.Activator + // + case "Activator" when methodCalledType.Namespace == "System": + if (!methodCalled.IsStatic) break; + switch (methodCalled.Name) { // - // System.Activator + // static T CreateInstance () // - case "Activator" when methodCalledType.Namespace == "System": - if (!methodCalled.IsStatic) + case "CreateInstance" when methodCalled.ContainsGenericParameter: + // Not sure it's worth implementing as we cannot expant T and simple cases can be rewritten + reflectionContext.AnalyzingPattern (); + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not supported"); + break; + + // + // static CreateInstance (string assemblyName, string typeName) + // static CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + // static CreateInstance (string assemblyName, string typeName, object?[]? activationAttributes) + // + // static CreateInstance (System.Type type) + // static CreateInstance (System.Type type, bool nonPublic) + // static CreateInstance (System.Type type, params object?[]? args) + // static CreateInstance (System.Type type, object?[]? args, object?[]? activationAttributes) + // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture) + // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } + // + case "CreateInstance": { + reflectionContext.AnalyzingPattern (); + + var parameters = methodCalled.Parameters; + if (parameters.Count < 1) break; - switch (methodCalled.Name) { - // - // static T CreateInstance () - // - case "CreateInstance" when methodCalled.ContainsGenericParameter: - // Not sure it's worth implementing as we cannot expant T and simple cases can be rewritten - reflectionContext.AnalyzingPattern (); - reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' is not supported"); - break; + if (parameters [0].ParameterType.MetadataType == MetadataType.String) { + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, parameters.Count < 4); + break; + } - // - // static CreateInstance (string assemblyName, string typeName) - // static CreateInstance (string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) - // static CreateInstance (string assemblyName, string typeName, object?[]? activationAttributes) - // - // static CreateInstance (System.Type type) - // static CreateInstance (System.Type type, bool nonPublic) - // static CreateInstance (System.Type type, params object?[]? args) - // static CreateInstance (System.Type type, object?[]? args, object?[]? activationAttributes) - // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture) - // static CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } - // - case "CreateInstance": { - reflectionContext.AnalyzingPattern (); - - var parameters = methodCalled.Parameters; - if (parameters.Count < 1) - break; - - if (parameters [0].ParameterType.MetadataType == MetadataType.String) { - ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, parameters.Count < 4); - break; - } - - var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); - if (first_arg_instr < 0) { - reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); - break; - } - - if (parameters [0].ParameterType.IsTypeOf ("System", "Type")) { - declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr + 1); - if (declaringType == null) { - reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument expression which cannot be analyzed"); - break; - } - - BindingFlags bindingFlags = BindingFlags.Instance; - int? parametersCount = null; - - if (methodCalled.Parameters.Count == 1) { - parametersCount = 0; - } else { - var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count - 1); - second_argument = _instructions [second_arg_instr]; - switch (second_argument.OpCode.Code) { - case Code.Ldc_I4_0 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: - parametersCount = 0; - bindingFlags |= BindingFlags.Public; - break; - case Code.Ldc_I4_1 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: - parametersCount = 0; - break; - case Code.Ldc_I4_S when parameters [1].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags"): - bindingFlags = (BindingFlags)(sbyte)second_argument.Operand; - break; - } - } - - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags, parametersCount); - break; - } - } + var first_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count); + if (first_arg_instr < 0) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' couldn't be decomposed"); + break; + } + if (parameters [0].ParameterType.IsTypeOf ("System", "Type")) { + declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr + 1); + if (declaringType is null) { + reflectionContext.RecordUnrecognizedPattern ($"Activator call '{methodCalled.FullName}' inside '{_methodCalling.FullName}' was detected with 1st argument expression which cannot be analyzed"); break; + } - // - // static CreateInstanceFrom (string assemblyFile, string typeName) - // static CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) - // static CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) - // - case "CreateInstanceFrom": - ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); - break; + BindingFlags bindingFlags = BindingFlags.Instance; + int? parametersCount = null; + + if (methodCalled.Parameters.Count == 1) { + parametersCount = 0; + } else { + var second_arg_instr = GetInstructionAtStackDepth (_instructions, instructionIndex - 1, methodCalled.Parameters.Count - 1); + second_argument = _instructions [second_arg_instr]; + switch (second_argument.OpCode.Code) { + case Code.Ldc_I4_0 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: + parametersCount = 0; + bindingFlags |= BindingFlags.Public; + break; + case Code.Ldc_I4_1 when parameters [1].ParameterType.MetadataType == MetadataType.Boolean: + parametersCount = 0; + break; + case Code.Ldc_I4_S when parameters [1].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags"): + bindingFlags = (BindingFlags) (sbyte) second_argument.Operand; + break; + } + } + + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags, parametersCount); + break; } + } + + break; + // + // static CreateInstanceFrom (string assemblyFile, string typeName) + // static CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object? []? args, System.Globalization.CultureInfo? culture, object? []? activationAttributes) + // static CreateInstanceFrom (string assemblyFile, string typeName, object? []? activationAttributes) + // + case "CreateInstanceFrom": + ProcessActivatorCallWithStrings (ref reflectionContext, instructionIndex - 1, methodCalled.Parameters.Count < 4); break; + } + + break; } } @@ -2956,21 +2950,21 @@ void ProcessActivatorCallWithStrings (ref ReflectionPatternContext reflectionCon return; } - string assembly_name = (string)first_arg.Operand; + string assembly_name = (string) first_arg.Operand; if (!_markStep._context.Resolver.AssemblyCache.TryGetValue (assembly_name, out var assembly)) { reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' references assembly '{assembly_name}' which could not be found"); return; } - string type_name = (string)second_arg.Operand; + string type_name = (string) second_arg.Operand; var declaringType = FindType (assembly, type_name); - if (declaringType == null) { + if (declaringType is null) { reflectionContext.RecordUnrecognizedPattern ($"Activator call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' references type '{type_name}' which could not be found"); return; } - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, null, defaultCtorOnly ? 0 : (int?)null); + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, null, defaultCtorOnly ? 0 : (int?) null); } // @@ -2996,7 +2990,7 @@ void ProcessSystemTypeGetMemberLikeCall (ref ReflectionPatternContext reflection if (memberTypes == System.Reflection.MemberTypes.Constructor) { if (first_arg.OpCode == OpCodes.Ldc_I4_S && reflectionContext.MethodCalled.Parameters.Count > 0 && reflectionContext.MethodCalled.Parameters [0].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags")) { - bindingFlags = (BindingFlags)(sbyte)first_arg.Operand; + bindingFlags = (BindingFlags) (sbyte) first_arg.Operand; } } else { // @@ -3007,45 +3001,45 @@ void ProcessSystemTypeGetMemberLikeCall (ref ReflectionPatternContext reflection return; } - name = (string)first_arg.Operand; + name = (string) first_arg.Operand; var pos_arg = _instructions [first_arg_instr + 1]; if (pos_arg.OpCode == OpCodes.Ldc_I4_S && reflectionContext.MethodCalled.Parameters.Count > 1 && reflectionContext.MethodCalled.Parameters [1].ParameterType.IsTypeOf ("System.Reflection", "BindingFlags")) { - bindingFlags = (BindingFlags)(sbyte)pos_arg.Operand; + bindingFlags = (BindingFlags) (sbyte) pos_arg.Operand; } } var declaringType = FindReflectionTypeForLookup (_instructions, first_arg_instr - 1); - if (declaringType == null) { + if (declaringType is null) { reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' does not use detectable instance type extraction"); return; } switch (memberTypes) { - case System.Reflection.MemberTypes.Constructor: - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags); - break; - case System.Reflection.MemberTypes.Method: - MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, 0, bindingFlags); - break; - case System.Reflection.MemberTypes.Field: - MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name); - break; - case System.Reflection.MemberTypes.Property: - MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name); - break; - case System.Reflection.MemberTypes.Event: - MarkEventsFromReflectionCall (ref reflectionContext, declaringType, name); - break; - default: - Debug.Fail ("Unsupported member type"); - reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' is of unexpected member type."); - break; + case System.Reflection.MemberTypes.Constructor: + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, ".ctor", 0, bindingFlags); + break; + case System.Reflection.MemberTypes.Method: + MarkMethodsFromReflectionCall (ref reflectionContext, declaringType, name, 0, bindingFlags); + break; + case System.Reflection.MemberTypes.Field: + MarkFieldsFromReflectionCall (ref reflectionContext, declaringType, name); + break; + case System.Reflection.MemberTypes.Property: + MarkPropertiesFromReflectionCall (ref reflectionContext, declaringType, name); + break; + case System.Reflection.MemberTypes.Event: + MarkEventsFromReflectionCall (ref reflectionContext, declaringType, name); + break; + default: + Debug.Fail ("Unsupported member type"); + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{_methodCalling.FullName}' is of unexpected member type."); + break; } } // - // arity == null for name match regardless of arity + // arity is null for name match regardless of arity // void MarkMethodsFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, int? arity, BindingFlags? bindingFlags, int? parametersCount = null) { @@ -3054,7 +3048,7 @@ void MarkMethodsFromReflectionCall (ref ReflectionPatternContext reflectionConte var mname = method.Name; // Either exact match or generic method with any arity when unspecified - if (mname != name && !(arity == null && mname.StartsWith (name, StringComparison.Ordinal) && mname.Length > name.Length + 2 && mname [name.Length + 1] == '`')) { + if (mname != name && !(arity is null && mname.StartsWith (name, StringComparison.Ordinal) && mname.Length > name.Length + 2 && mname [name.Length + 1] == '`')) { continue; } @@ -3070,7 +3064,7 @@ void MarkMethodsFromReflectionCall (ref ReflectionPatternContext reflectionConte if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic && method.IsPublic) continue; - if (parametersCount != null && parametersCount != method.Parameters.Count) + if (parametersCount is not null && parametersCount != method.Parameters.Count) continue; foundMatch = true; @@ -3093,13 +3087,13 @@ void MarkPropertiesFromReflectionCall (ref ReflectionPatternContext reflectionCo // It is not easy to reliably detect in the IL code whether the getter or setter (or both) are used. // Be conservative and mark everything for the property. var getter = property.GetMethod; - if (getter != null && (!staticOnly || staticOnly && getter.IsStatic)) { + if (getter is not null && (!staticOnly || staticOnly && getter.IsStatic)) { reflectionContext.RecordRecognizedPattern (getter, () => _markStep.MarkIndirectlyCalledMethod (getter)); markedAny = true; } var setter = property.SetMethod; - if (setter != null && (!staticOnly || staticOnly && setter.IsStatic)) { + if (setter is not null && (!staticOnly || staticOnly && setter.IsStatic)) { reflectionContext.RecordRecognizedPattern (setter, () => _markStep.MarkIndirectlyCalledMethod (setter)); markedAny = true; } @@ -3284,11 +3278,11 @@ static TypeDefinition FindReflectionTypeForLookup (Collection instr startIndex = storeIndex - 1; break; case Code.Ldloc_S: - storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_S, startIndex - 1, l => (VariableReference)l.Operand == (VariableReference)instruction.Operand); + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc_S, startIndex - 1, l => (VariableReference) l.Operand == (VariableReference) instruction.Operand); startIndex = storeIndex - 1; break; case Code.Ldloc: - storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc, startIndex - 1, l => (VariableReference)l.Operand == (VariableReference)instruction.Operand); + storeIndex = GetIndexOfInstruction (instructions, OpCodes.Stloc, startIndex - 1, l => (VariableReference) l.Operand == (VariableReference) instruction.Operand); startIndex = storeIndex - 1; break; @@ -3308,7 +3302,7 @@ static int GetIndexOfInstruction (Collection instructions, OpCode o { while (startIndex >= 0) { var instr = instructions [startIndex]; - if (instr.OpCode == opcode && (comparer == null || comparer (instr))) + if (instr.OpCode == opcode && (comparer is null || comparer (instr))) return startIndex; startIndex--; @@ -3331,8 +3325,7 @@ public AttributeProviderPair (CustomAttribute attribute, ICustomAttributeProvide // Make our own copy of the BindingFlags enum, so that we don't depend on System.Reflection. [Flags] - enum BindingFlags - { + enum BindingFlags { Default = 0, IgnoreCase = 1, DeclaredOnly = 2, diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs index 884f6a9a65f0..d4e52806c53d 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/OutputStep.cs @@ -50,18 +50,19 @@ private enum NativeOSOverride { List assembliesWritten; - public OutputStep () { + public OutputStep () + { assembliesWritten = new List (); } static TargetArchitecture CalculateArchitecture (TargetArchitecture readyToRunArch) { - if (architectureMap == null) { + if (architectureMap is null) { architectureMap = new Dictionary (); foreach (var os in Enum.GetValues (typeof (NativeOSOverride))) { ushort osVal = (ushort) (NativeOSOverride) os; foreach (var arch in Enum.GetValues (typeof (TargetArchitecture))) { - ushort archVal = (ushort) (TargetArchitecture)arch; + ushort archVal = (ushort) (TargetArchitecture) arch; architectureMap.Add ((ushort) (archVal ^ osVal), (TargetArchitecture) arch); } } @@ -82,7 +83,7 @@ protected override void Process () protected override void EndProcess () { - if (Context.AssemblyListFile != null) { + if (Context.AssemblyListFile is not null) { using (var w = File.CreateText (Context.AssemblyListFile)) { w.WriteLine ("[" + String.Join (", ", assembliesWritten.Select (a => "\"" + a + "\"").ToArray ()) + "]"); } @@ -161,7 +162,7 @@ void OutputAssembly (AssemblyDefinition assembly) } } - protected virtual void DeleteAssembly(AssemblyDefinition assembly, string directory) + protected virtual void DeleteAssembly (AssemblyDefinition assembly, string directory) { var target = GetAssemblyFileName (assembly, directory); if (File.Exists (target)) { @@ -193,7 +194,7 @@ WriterParameters SaveSymbols (AssemblyDefinition assembly) if (Environment.OSVersion.Platform != PlatformID.Win32NT && assembly.MainModule.SymbolReader.GetType ().FullName == "Mono.Cecil.Pdb.NativePdbReader") return parameters; - if (Context.SymbolWriterProvider != null) + if (Context.SymbolWriterProvider is not null) parameters.SymbolWriterProvider = Context.SymbolWriterProvider; else parameters.WriteSymbols = true; @@ -281,7 +282,8 @@ protected virtual void CopyAssembly (AssemblyDefinition assembly, string directo CopyFileAndRemoveReadOnly (pdb, Path.ChangeExtension (target, "pdb")); } - static void CopyFileAndRemoveReadOnly (string src, string dest) { + static void CopyFileAndRemoveReadOnly (string src, string dest) + { File.Copy (src, dest, true); System.IO.FileAttributes attrs = File.GetAttributes (dest); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs index 437c67d73005..0ff917d71666 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/PreserveDependencyLookupStep.cs @@ -87,11 +87,11 @@ void ProcessPreserveDependencyAttribute (Collection attributes) continue; var assemblyName = ca.ConstructorArguments [2].Value as string; - if (assemblyName == null) + if (assemblyName is null) continue; var newDependency = Context.Resolve (new AssemblyNameReference (assemblyName, new Version ())); - if (newDependency != null) + if (newDependency is not null) ProcessReferences (newDependency); } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs index f8a350a08e07..94d317e9f153 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromAssemblyStep.cs @@ -1,4 +1,4 @@ -// +// // ResolveFromAssemblyStep.cs // // Author: @@ -29,18 +29,15 @@ using Mono.Cecil; using Mono.Collections.Generic; -namespace Mono.Linker.Steps -{ +namespace Mono.Linker.Steps { - public class ResolveFromAssemblyStep : ResolveStep - { + public class ResolveFromAssemblyStep : ResolveStep { AssemblyDefinition _assembly; string _file; RootVisibility _rootVisibility; - public enum RootVisibility - { + public enum RootVisibility { Any = 0, PublicAndFamily = 1, PublicAndFamilyAndAssembly = 2 @@ -60,7 +57,7 @@ public ResolveFromAssemblyStep (AssemblyDefinition assembly) protected override void Process () { - if (_assembly != null) + if (_assembly is not null) Context.Resolver.CacheAssembly (_assembly); var ignoreUnresolved = Context.Resolver.IgnoreUnresolved; @@ -103,7 +100,7 @@ public static void ProcessLibrary (LinkContext context, AssemblyDefinition assem foreach (var exported in assembly.MainModule.ExportedTypes) { bool isForwarder = exported.IsForwarder; var declaringType = exported.DeclaringType; - while (!isForwarder && (declaringType != null)) { + while (!isForwarder && (declaringType is not null)) { isForwarder = declaringType.IsForwarder; declaringType = declaringType.DeclaringType; } @@ -112,7 +109,7 @@ public static void ProcessLibrary (LinkContext context, AssemblyDefinition assem continue; TypeDefinition resolvedExportedType = exported.Resolve (); - if (resolvedExportedType == null) { + if (resolvedExportedType is null) { // // It's quite common for assemblies to have broken exported types // diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs index 57e277400870..3d4f7099cea1 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXApiStep.cs @@ -1,4 +1,4 @@ -// +// // ResolveFromXApiStep.cs // // Author: @@ -30,11 +30,9 @@ using Mono.Cecil; -namespace Mono.Linker.Steps -{ +namespace Mono.Linker.Steps { - public class ResolveFromXApiStep : ResolveStep, IXApiVisitor - { + public class ResolveFromXApiStep : ResolveStep, IXApiVisitor { static readonly string _name = "name"; static readonly string _ns = string.Empty; @@ -61,7 +59,7 @@ public void OnAttribute (XPathNavigator nav) string name = GetName (nav); TypeDefinition type = Context.GetType (name); - if (type != null) + if (type is not null) MarkType (type); } @@ -96,11 +94,11 @@ public void OnProperty (XPathNavigator nav, PropertyDefinition property) public void OnEvent (XPathNavigator nav, EventDefinition evt) { - if (evt.AddMethod != null) + if (evt.AddMethod is not null) MarkMethod (evt.AddMethod); - if (evt.InvokeMethod != null) + if (evt.InvokeMethod is not null) MarkMethod (evt.InvokeMethod); - if (evt.RemoveMethod != null) + if (evt.RemoveMethod is not null) MarkMethod (evt.RemoveMethod); } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs index bb4febed88ba..8f794173b839 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveFromXmlStep.cs @@ -54,8 +54,8 @@ public class ResolveFromXmlStep : ResolveStep { static readonly string _accessors = "accessors"; static readonly string _ns = string.Empty; - static readonly string[] _accessorsAll = new string[] { "all" }; - static readonly char[] _accessorsSep = new char[] { ';' }; + static readonly string [] _accessorsAll = new string [] { "all" }; + static readonly char [] _accessorsSep = new char [] { ';' }; XPathDocument _document; string _xmlDocumentLocation; @@ -74,7 +74,7 @@ public ResolveFromXmlStep (XPathDocument document, string resourceName, Assembly if (string.IsNullOrEmpty (resourceName)) throw new ArgumentNullException (nameof (resourceName)); - if (resourceAssembly == null) + if (resourceAssembly is null) throw new ArgumentNullException (nameof (resourceAssembly)); _resourceName = resourceName; @@ -87,7 +87,7 @@ protected override void Process () // This step can be created with XML files that aren't necessarily // linker descriptor files. So bail if we don't have a element. - if (!nav.MoveToChild("linker", _ns)) + if (!nav.MoveToChild ("linker", _ns)) return; try { @@ -104,7 +104,7 @@ protected virtual void ProcessAssemblies (LinkContext context, XPathNodeIterator { while (iterator.MoveNext ()) { AssemblyDefinition assembly = GetAssembly (context, GetAssemblyName (iterator.Current)); - if (assembly != null) + if (assembly is not null) ProcessAssembly (assembly, iterator); } } @@ -168,7 +168,7 @@ void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator) TypeDefinition type = assembly.MainModule.GetType (fullname); - if (type == null) { + if (type is null) { if (assembly.MainModule.HasExportedTypes) { foreach (var exported in assembly.MainModule.ExportedTypes) { if (fullname == exported.FullName) { @@ -176,7 +176,7 @@ void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator) MarkingHelpers.MarkExportedType (exported, assembly.MainModule); var resolvedExternal = exported.Resolve (); Tracer.Pop (); - if (resolvedExternal != null) { + if (resolvedExternal is not null) { type = resolvedExternal; break; } @@ -185,7 +185,7 @@ void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator) } } - if (type == null) + if (type is null) continue; ProcessType (type, nav); @@ -219,7 +219,7 @@ void MatchExportedType (ExportedType exportedType, ModuleDefinition module, Rege if (regex.Match (exportedType.FullName).Success) { MarkingHelpers.MarkExportedType (exportedType, module); TypeDefinition type = exportedType.Resolve (); - if (type != null) { + if (type is not null) { ProcessType (type, nav); } } @@ -245,7 +245,7 @@ protected virtual void ProcessType (TypeDefinition type, XPathNavigator nav) { if (IsExcluded (nav)) return; - + TypePreserve preserve = GetTypePreserve (nav); if (!IsRequired (nav)) { @@ -253,11 +253,11 @@ protected virtual void ProcessType (TypeDefinition type, XPathNavigator nav) return; } - if (Annotations.IsMarked (type)) { - var existingLevel = Annotations.TryGetPreserve (type, out TypePreserve existingPreserve) ? existingPreserve : TypePreserve.Nothing; - var duplicateLevel = preserve != TypePreserve.Nothing ? preserve : nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All; - Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {type.FullName} ({existingLevel}). Duplicate uses ({duplicateLevel})"); - } + if (Annotations.IsMarked (type)) { + var existingLevel = Annotations.TryGetPreserve (type, out TypePreserve existingPreserve) ? existingPreserve : TypePreserve.Nothing; + var duplicateLevel = preserve != TypePreserve.Nothing ? preserve : nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All; + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {type.FullName} ({existingLevel}). Duplicate uses ({duplicateLevel})"); + } Annotations.MarkAndPush (type); Tracer.AddDirectDependency (this, type); @@ -340,7 +340,7 @@ protected virtual void ProcessField (TypeDefinition type, XPathNodeIterator iter { if (IsExcluded (iterator.Current)) return; - + string value = GetSignature (iterator.Current); if (!String.IsNullOrEmpty (value)) ProcessFieldSignature (type, value); @@ -358,10 +358,10 @@ void ProcessFieldSignature (TypeDefinition type, string signature) void MarkField (TypeDefinition type, FieldDefinition field, string signature) { - if (field != null) { + if (field is not null) { if (Annotations.IsMarked (field)) Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {field.FullName}"); - + Annotations.Mark (field); } else { AddUnresolveMarker (string.Format ("T: {0}; F: {1}", type, signature)); @@ -405,7 +405,7 @@ protected virtual void ProcessMethod (TypeDefinition type, XPathNodeIterator ite { if (IsExcluded (iterator.Current)) return; - + string value = GetSignature (iterator.Current); if (!String.IsNullOrEmpty (value)) ProcessMethodSignature (type, value); @@ -423,7 +423,7 @@ void ProcessMethodSignature (TypeDefinition type, string signature) void MarkMethod (TypeDefinition type, MethodDefinition method, string signature) { - if (method != null) { + if (method is not null) { MarkMethod (method); } else AddUnresolveMarker (string.Format ("T: {0}; M: {1}", type, signature)); @@ -431,8 +431,8 @@ void MarkMethod (TypeDefinition type, MethodDefinition method, string signature) void MarkMethod (MethodDefinition method) { - if (Annotations.IsMarked (method)) - Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {method.FullName}"); + if (Annotations.IsMarked (method)) + Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {method.FullName}"); Annotations.Mark (method); Annotations.MarkIndirectlyCalledMethod (method); @@ -442,7 +442,7 @@ void MarkMethod (MethodDefinition method) void MarkMethodIfNotNull (MethodDefinition method) { - if (method == null) + if (method is null) return; MarkMethod (method); @@ -502,7 +502,7 @@ protected virtual void ProcessEvent (TypeDefinition type, XPathNodeIterator iter { if (IsExcluded (iterator.Current)) return; - + string value = GetSignature (iterator.Current); if (!String.IsNullOrEmpty (value)) ProcessEventSignature (type, value); @@ -520,7 +520,7 @@ void ProcessEventSignature (TypeDefinition type, string signature) void MarkEvent (TypeDefinition type, EventDefinition @event, string signature) { - if (@event != null) { + if (@event is not null) { if (Annotations.IsMarked (@event)) Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {@event.FullName}"); @@ -570,7 +570,7 @@ protected virtual void ProcessProperty (TypeDefinition type, XPathNodeIterator i { if (IsExcluded (iterator.Current)) return; - + string value = GetSignature (iterator.Current); if (!String.IsNullOrEmpty (value)) ProcessPropertySignature (type, value, GetAccessors (iterator.Current)); @@ -580,18 +580,18 @@ protected virtual void ProcessProperty (TypeDefinition type, XPathNodeIterator i ProcessPropertyName (type, value, _accessorsAll); } - void ProcessPropertySignature (TypeDefinition type, string signature, string[] accessors) + void ProcessPropertySignature (TypeDefinition type, string signature, string [] accessors) { PropertyDefinition property = GetProperty (type, signature); MarkProperty (type, property, signature, accessors); } - void MarkProperty (TypeDefinition type, PropertyDefinition property, string signature, string[] accessors) + void MarkProperty (TypeDefinition type, PropertyDefinition property, string signature, string [] accessors) { - if (property != null) { + if (property is not null) { if (Annotations.IsMarked (property)) Context.LogMessage ($"Duplicate preserve in {_xmlDocumentLocation} of {property.FullName}"); - + Annotations.Mark (property); MarkPropertyAccessors (type, property, accessors); @@ -599,7 +599,7 @@ void MarkProperty (TypeDefinition type, PropertyDefinition property, string sign AddUnresolveMarker (string.Format ("T: {0}; P: {1}", type, signature)); } - void MarkPropertyAccessors (TypeDefinition type, PropertyDefinition property, string[] accessors) + void MarkPropertyAccessors (TypeDefinition type, PropertyDefinition property, string [] accessors) { if (Array.IndexOf (accessors, "all") >= 0) { MarkMethodIfNotNull (property.GetMethod); @@ -607,20 +607,20 @@ void MarkPropertyAccessors (TypeDefinition type, PropertyDefinition property, st return; } - if (property.GetMethod != null + if (property.GetMethod is not null && Array.IndexOf (accessors, "get") >= 0) MarkMethod (property.GetMethod); - else if (property.GetMethod == null) + else if (property.GetMethod is null) AddUnresolveMarker (string.Format ("T: {0}' M: {1} get_{2}", type, property.PropertyType, property.Name)); - - if (property.SetMethod != null + + if (property.SetMethod is not null && Array.IndexOf (accessors, "set") >= 0) MarkMethod (property.SetMethod); - else if (property.SetMethod == null) + else if (property.SetMethod is null) AddUnresolveMarker (string.Format ("T: {0}' M: System.Void set_{2} ({1})", type, property.PropertyType, property.Name)); } - void ProcessPropertyName (TypeDefinition type, string name, string[] accessors) + void ProcessPropertyName (TypeDefinition type, string name, string [] accessors) { if (!type.HasProperties) return; @@ -667,7 +667,7 @@ static void ProcessReferences (AssemblyDefinition assembly, LinkContext context) static bool IsRequired (XPathNavigator nav) { string attribute = GetAttribute (nav, _required); - if (attribute == null || attribute.Length == 0) + if (attribute is null || attribute.Length == 0) return true; bool result; @@ -686,17 +686,17 @@ static string GetFullName (XPathNavigator nav) return GetAttribute (nav, _fullname); } - protected static string[] GetAccessors (XPathNavigator nav) + protected static string [] GetAccessors (XPathNavigator nav) { string accessorsValue = GetAttribute (nav, _accessors); - if (accessorsValue != null) { - string[] accessors = accessorsValue.Split ( + if (accessorsValue is not null) { + string [] accessors = accessorsValue.Split ( _accessorsSep, StringSplitOptions.RemoveEmptyEntries); if (accessors.Length > 0) { for (int i = 0; i < accessors.Length; ++i) - accessors[i] = accessors[i].ToLower (); + accessors [i] = accessors [i].ToLower (); return accessors; } @@ -708,7 +708,7 @@ protected static string GetAttribute (XPathNavigator nav, string attribute) { return nav.GetAttribute (attribute, _ns); } - + protected virtual bool IsExcluded (XPathNavigator nav) { var value = GetAttribute (nav, "feature"); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs index 49503f93692c..604728bef247 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/ResolveStep.cs @@ -1,4 +1,4 @@ -// +// // ResolveStep.cs // // Author: @@ -39,8 +39,7 @@ protected ResolveStep () _unResolved = new List (); } - public bool AllMarkerResolved - { + public bool AllMarkerResolved { get { return _unResolved.Count == 0; } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs index 8bcf11175e0f..dd1e411be8c1 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/SweepStep.cs @@ -1,4 +1,4 @@ -// +// // SweepStep.cs // // Author: @@ -35,8 +35,7 @@ namespace Mono.Linker.Steps { - public class SweepStep : BaseStep - { + public class SweepStep : BaseStep { AssemblyDefinition [] assemblies; readonly bool sweepSymbols; readonly HashSet BypassNGenToSave = new HashSet (); @@ -189,12 +188,12 @@ protected virtual void RemoveAssembly (AssemblyDefinition assembly) void SweepResources (AssemblyDefinition assembly) { var resourcesToRemove = Annotations.GetResourcesToRemove (assembly); - if (resourcesToRemove != null) { + if (resourcesToRemove is not null) { var resources = assembly.MainModule.Resources; for (int i = 0; i < resources.Count; i++) { var resource = resources [i] as EmbeddedResource; - if (resource == null) + if (resource is null) continue; if (resourcesToRemove.Contains (resource.Name)) @@ -215,7 +214,7 @@ void SweepReferences (AssemblyDefinition assembly, AssemblyDefinition referenceT var reference = references [i]; AssemblyDefinition ad = Context.Resolver.Resolve (reference); - if (ad == null || !AreSameReference (ad.Name, referenceToRemove.Name)) + if (ad is null || !AreSameReference (ad.Name, referenceToRemove.Name)) continue; ReferenceRemoved (assembly, reference); @@ -291,7 +290,7 @@ void UpdateForwardedTypesScope (AssemblyDefinition assembly) // 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)) + if (td is null || !Annotations.IsMarked (td)) continue; IMetadataScope scope = assembly.MainModule.ImportReference (td).Scope; @@ -311,7 +310,7 @@ void UpdateForwardedTypesScope (AssemblyDefinition assembly) if (assembly.MainModule.HasExportedTypes) { foreach (var et in assembly.MainModule.ExportedTypes) { var td = et.Resolve (); - if (td == null) + if (td is null) continue; et.Scope = assembly.MainModule.ImportReference (td).Scope; @@ -332,7 +331,7 @@ static void UpdateCustomAttributesTypesScopes (AssemblyDefinition assembly) static void UpdateCustomAttributesTypesScopes (TypeDefinition typeDefinition) { - UpdateCustomAttributesTypesScopes ((ICustomAttributeProvider)typeDefinition); + UpdateCustomAttributesTypesScopes ((ICustomAttributeProvider) typeDefinition); if (typeDefinition.HasEvents) UpdateCustomAttributesTypesScopes (typeDefinition.Events); @@ -412,7 +411,7 @@ static void UpdateForwardedTypesScope (CustomAttributeArgument attributeArgument case CustomAttributeArgument caa: UpdateForwardedTypesScope (caa, assembly); break; - case CustomAttributeArgument[] array: + case CustomAttributeArgument [] array: foreach (var item in array) UpdateForwardedTypesScope (item, assembly); break; @@ -438,7 +437,7 @@ static void UpdateTypeScope (TypeReference type, AssemblyDefinition assembly) } TypeDefinition td = type.Resolve (); - if (td == null) + if (td is null) return; IMetadataScope scope = assembly.MainModule.ImportReference (td).Scope; @@ -542,21 +541,21 @@ bool ShouldSetHasSecurityToFalse (ISecurityDeclarationProvider providerAsSecurit static bool IsSecurityAttributeType (TypeDefinition definition) { - if (definition == null) + if (definition is null) return false; if (definition.Namespace == "System.Security") { switch (definition.FullName) { - // This seems to be one attribute in the System.Security namespace that doesn't count - // as an attribute that requires HasSecurity to be true - case "System.Security.SecurityCriticalAttribute": - return false; + // This seems to be one attribute in the System.Security namespace that doesn't count + // as an attribute that requires HasSecurity to be true + case "System.Security.SecurityCriticalAttribute": + return false; } return true; } - if (definition.BaseType == null) + if (definition.BaseType is null) return false; return IsSecurityAttributeType (definition.BaseType.Resolve ()); @@ -564,7 +563,7 @@ static bool IsSecurityAttributeType (TypeDefinition definition) protected IList SweepCustomAttributes (ICustomAttributeProvider provider) { - var removed = new List(); + var removed = new List (); for (int i = provider.CustomAttributes.Count - 1; i >= 0; i--) { var attribute = provider.CustomAttributes [i]; @@ -610,14 +609,14 @@ void SweepDebugInfo (Collection methods) { List sweptScopes = null; foreach (var m in methods) { - if (m.DebugInformation == null) + if (m.DebugInformation is null) continue; var scope = m.DebugInformation.Scope; - if (scope == null) + if (scope is null) continue; - if (sweptScopes == null) { + if (sweptScopes is null) { sweptScopes = new List (); } else if (sweptScopes.Contains (scope)) { continue; @@ -634,12 +633,12 @@ void SweepDebugInfo (Collection methods) } var import = scope.Import; - while (import != null) { + while (import is not null) { if (import.HasTargets) { var targets = import.Targets; for (int i = 0; i < targets.Count; ++i) { var ttype = targets [i].Type; - if (ttype != null && !Annotations.IsMarked (ttype)) + if (ttype is not null && !Annotations.IsMarked (ttype)) targets.RemoveAt (i--); // TODO: Clear also AssemblyReference and Namespace when not marked diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs index 32727fa65e61..053ad77373d9 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker.Steps/TypeMapStep.cs @@ -1,4 +1,4 @@ -// +// // TypeMapStep.cs // // Author: @@ -60,9 +60,9 @@ void MapInterfaceHierarchy (TypeDefinition type) foreach (var iface in type.Interfaces) { var resolved = iface.InterfaceType.Resolve (); - if (resolved == null) + if (resolved is null) continue; - + Annotations.AddDerivedInterfaceForInterface (resolved, type); } } @@ -75,21 +75,21 @@ void MapInterfaceMethodsInTypeHierarchy (TypeDefinition type) foreach (var @interface in type.Interfaces) { var interfaceType = @interface.InterfaceType; var iface = interfaceType.Resolve (); - if (iface == null || !iface.HasMethods) + if (iface is null || !iface.HasMethods) continue; foreach (MethodDefinition interfaceMethod in iface.Methods) { - if (TryMatchMethod (type, interfaceMethod) != null) + if (TryMatchMethod (type, interfaceMethod) is not null) continue; var @base = GetBaseMethodInTypeHierarchy (type, interfaceMethod); - if (@base != null) + if (@base is not null) AnnotateMethods (interfaceMethod, @base, @interface); if (interfaceType is GenericInstanceType genericInterfaceInstance) { var genericContext = new Inflater.GenericContext (genericInterfaceInstance, null); var baseInflated = GetBaseInflatedInterfaceMethodInTypeHierarchy (genericContext, type, interfaceMethod); - if (baseInflated != null) + if (baseInflated is not null) Annotations.AddOverride (interfaceMethod, baseInflated, @interface); } } @@ -98,14 +98,14 @@ void MapInterfaceMethodsInTypeHierarchy (TypeDefinition type) static MethodReference CreateGenericInstanceCandidate (Inflater.GenericContext context, TypeDefinition candidateType, MethodDefinition interfaceMethod) { - var methodReference = new MethodReference (interfaceMethod.Name, interfaceMethod.ReturnType, candidateType) {HasThis = interfaceMethod.HasThis}; - + var methodReference = new MethodReference (interfaceMethod.Name, interfaceMethod.ReturnType, candidateType) { HasThis = interfaceMethod.HasThis }; + foreach (var genericMethodParameter in interfaceMethod.GenericParameters) methodReference.GenericParameters.Add (new GenericParameter (genericMethodParameter.Name, methodReference)); - + if (interfaceMethod.ReturnType.IsGenericParameter || interfaceMethod.ReturnType.IsGenericInstance) methodReference.ReturnType = Inflater.InflateType (context, interfaceMethod.ReturnType); - + foreach (var p in interfaceMethod.Parameters) { var parameterType = p.ParameterType; if (parameterType.IsGenericParameter || parameterType.IsGenericInstance) @@ -142,7 +142,7 @@ void MapVirtualMethod (MethodDefinition method) void MapVirtualBaseMethod (MethodDefinition method) { MethodDefinition @base = GetBaseMethodInTypeHierarchy (method); - if (@base == null) + if (@base is null) return; AnnotateMethods (@base, method); @@ -158,7 +158,7 @@ void MapOverrides (MethodDefinition method) { foreach (MethodReference override_ref in method.Overrides) { MethodDefinition @override = override_ref.Resolve (); - if (@override == null) + if (@override is null) continue; AnnotateMethods (@override, method); @@ -173,13 +173,13 @@ void MapBaseTypeHierarchy (TypeDefinition type) var bases = new List (); var current = type.BaseType; - while (current != null) { + while (current is not null) { var resolved = current.Resolve (); - if (resolved == null) + if (resolved is null) break; // Exclude Object. That's implied and adding it to the list will just lead to lots of extra unnecessary processing - if (resolved.BaseType == null) + if (resolved.BaseType is null) break; bases.Add (resolved); @@ -203,9 +203,9 @@ static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) static MethodDefinition GetBaseMethodInTypeHierarchy (TypeDefinition type, MethodDefinition method) { TypeReference @base = type.GetInflatedBaseType (); - while (@base != null) { + while (@base is not null) { MethodDefinition base_method = TryMatchMethod (@base, method); - if (base_method != null) + if (base_method is not null) return base_method; @base = @base.GetInflatedBaseType (); @@ -217,11 +217,11 @@ static MethodDefinition GetBaseMethodInTypeHierarchy (TypeDefinition type, Metho static MethodDefinition GetBaseInflatedInterfaceMethodInTypeHierarchy (Inflater.GenericContext context, TypeDefinition type, MethodDefinition interfaceMethod) { TypeReference @base = type.GetInflatedBaseType (); - while (@base != null) { + while (@base is not null) { var candidate = CreateGenericInstanceCandidate (context, @base.Resolve (), interfaceMethod); - + MethodDefinition base_method = TryMatchMethod (@base, candidate); - if (base_method != null) + if (base_method is not null) return base_method; @base = @base.GetInflatedBaseType (); @@ -239,7 +239,7 @@ static IEnumerable GetBaseMethodsInInterfaceHierarchy (TypeRef { foreach (TypeReference @interface in type.GetInflatedInterfaces ()) { MethodDefinition base_method = TryMatchMethod (@interface, method); - if (base_method != null) + if (base_method is not null) yield return base_method; foreach (MethodDefinition @base in GetBaseMethodsInInterfaceHierarchy (@interface, method)) @@ -308,11 +308,11 @@ static bool TypeMatch (IModifierType a, IModifierType b) static bool TypeMatch (TypeSpecification a, TypeSpecification b) { var gita = a as GenericInstanceType; - if (gita != null) + if (gita is not null) return TypeMatch (gita, (GenericInstanceType) b); var mta = a as IModifierType; - if (mta != null) + if (mta is not null) return TypeMatch (mta, (IModifierType) b); return TypeMatch (a.ElementType, b.ElementType); @@ -363,7 +363,7 @@ static bool TypeMatch (TypeReference a, TypeReference b) } if (a is GenericParameter && b is GenericParameter) - return TypeMatch ((GenericParameter)a, (GenericParameter)b); + return TypeMatch ((GenericParameter) a, (GenericParameter) b); return a.FullName == b.FullName; } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs index 627d8121ea84..c060892ba545 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Annotations.cs @@ -52,14 +52,14 @@ public partial class AnnotationStore { protected readonly Dictionary> base_methods = new Dictionary> (); protected readonly Dictionary symbol_readers = new Dictionary (); protected readonly Dictionary> class_type_base_hierarchy = new Dictionary> (); - protected readonly Dictionary> derived_interfaces = new Dictionary>(); + protected readonly Dictionary> derived_interfaces = new Dictionary> (); protected readonly Dictionary> custom_annotations = new Dictionary> (); protected readonly Dictionary> resources_to_remove = new Dictionary> (); protected readonly HashSet marked_attributes = new HashSet (); readonly HashSet marked_types_with_cctor = new HashSet (); protected readonly HashSet marked_instantiated = new HashSet (); - protected readonly HashSet indirectly_called = new HashSet(); + protected readonly HashSet indirectly_called = new HashSet (); public AnnotationStore (LinkContext context) => this.context = context; @@ -95,7 +95,7 @@ public AssemblyAction GetAction (AssemblyDefinition assembly) if (assembly_actions.TryGetValue (assembly, out action)) return action; - throw new InvalidOperationException($"No action for the assembly {assembly.Name} defined"); + throw new InvalidOperationException ($"No action for the assembly {assembly.Name} defined"); } public MethodAction GetAction (MethodDefinition method) @@ -308,7 +308,7 @@ public bool IsPublic (IMetadataTokenProvider provider) public void AddOverride (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) { var methods = GetOverrides (@base); - if (methods == null) { + if (methods is null) { methods = new List (); override_methods [@base] = methods; } @@ -328,7 +328,7 @@ public List GetOverrides (MethodDefinition method) public void AddBaseMethod (MethodDefinition method, MethodDefinition @base) { var methods = GetBaseMethods (method); - if (methods == null) { + if (methods is null) { methods = new List (); base_methods [method] = methods; } @@ -377,7 +377,7 @@ List GetPreservedMethods (IMemberDefinition definition) void AddPreservedMethod (IMemberDefinition definition, MethodDefinition method) { var methods = GetPreservedMethods (definition); - if (methods == null) { + if (methods is null) { methods = new List (); preserved_methods [definition] = methods; } @@ -445,15 +445,15 @@ public void AddDerivedInterfaceForInterface (TypeDefinition @base, TypeDefinitio List derivedInterfaces; if (!derived_interfaces.TryGetValue (@base, out derivedInterfaces)) derived_interfaces [@base] = derivedInterfaces = new List (); - - derivedInterfaces.Add(derived); + + derivedInterfaces.Add (derived); } public List GetDerivedInterfacesForInterface (TypeDefinition @interface) { if (!@interface.IsInterface) throw new ArgumentException ($"{nameof (@interface)} must be an interface"); - + List derivedInterfaces; if (derived_interfaces.TryGetValue (@interface, out derivedInterfaces)) return derivedInterfaces; diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs index 143a7559f1be..0b7367539c00 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/AssemblyResolver.cs @@ -1,4 +1,4 @@ -// +// // AssemblyResolver.cs // // Author: @@ -76,7 +76,7 @@ public LinkContext Context { // The base class's definition of GetAssembly is visible when using DirectoryAssemblyResolver. AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) { - if (parameters.AssemblyResolver == null) + if (parameters.AssemblyResolver is null) parameters.AssemblyResolver = this; return ModuleDefinition.ReadModule (file, parameters).Assembly; @@ -102,19 +102,19 @@ AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { // Validate arguments, similarly to how the base class does it. - if (name == null) + if (name is null) throw new ArgumentNullException ("name"); - if (parameters == null) + if (parameters is null) throw new ArgumentNullException ("parameters"); AssemblyDefinition asm = null; - if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { + if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies is null || !_unresolvedAssemblies.Contains (name.Name))) { try { // Any full path explicit reference takes precedence over other look up logic asm = ResolveFromReferences (name, _references, parameters); // Fall back to the base class resolution logic - if (asm == null) + if (asm is null) asm = base.Resolve (name, parameters); _assemblies [name.Name] = asm; @@ -122,7 +122,7 @@ public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderPa if (!_ignoreUnresolved) throw; _context.LogMessage ($"warning: Ignoring unresolved assembly '{name.Name}'."); - if (_unresolvedAssemblies == null) + if (_unresolvedAssemblies is null) _unresolvedAssemblies = new HashSet (); _unresolvedAssemblies.Add (name.Name); } @@ -150,7 +150,7 @@ protected override void Dispose (bool disposing) } _assemblies.Clear (); - if (_unresolvedAssemblies != null) + if (_unresolvedAssemblies is not null) _unresolvedAssemblies.Clear (); } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs index b4f62ce88beb..c0f504e587dc 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/BCL.cs @@ -1,21 +1,18 @@ -using Mono.Cecil; +using Mono.Cecil; -namespace Mono.Linker -{ - public static class BCL - { - public static class EventTracingForWindows - { +namespace Mono.Linker { + public static class BCL { + public static class EventTracingForWindows { public static bool IsEventSourceImplementation (TypeDefinition type, LinkContext context = null) { if (!type.IsClass) return false; - while (type.BaseType != null) { + while (type.BaseType is not null) { var bt = type.BaseType.Resolve (); - if (bt == null) { - if (context != null && !context.IgnoreUnresolved) + if (bt is null) { + if (context is not null && !context.IgnoreUnresolved) throw new ResolutionException (type.BaseType); break; @@ -60,7 +57,7 @@ public static bool IsIDisposableImplementation (MethodDefinition method) return true; } - static readonly string[] corlibNames = new [] { + static readonly string [] corlibNames = new [] { "mscorlib", "System.Runtime", "System.Private.CoreLib", @@ -77,7 +74,7 @@ public static TypeDefinition FindPredefinedType (string ns, string name, LinkCon TypeDefinition type = corlib.MainModule.GetType (ns, name); // The assembly could be a facade with type forwarders, in which case we don't find the type in this assembly. - if (type != null) + if (type is not null) return type; } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs index f7059f2b89f2..49305240d619 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ConsoleLogger.cs @@ -1,9 +1,7 @@ -using System; -namespace Mono.Linker -{ - public class ConsoleLogger : ILogger - { - public void LogMessage (MessageImportance importance, string message, params object[] values) +using System; +namespace Mono.Linker { + public class ConsoleLogger : ILogger { + public void LogMessage (MessageImportance importance, string message, params object [] values) { Console.WriteLine (message, values); } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs index de4e4616e943..7ad5b6b8c553 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IDependencyRecorder.cs @@ -1,4 +1,4 @@ -// +// // IDependencyRecorder.cs // // Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com) @@ -23,14 +23,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -namespace Mono.Linker -{ +namespace Mono.Linker { /// /// Abstraction exposed by the linker (mostly MarkStep, but not only) - it will call this interface /// every time it finds a dependency between two parts of the dependency graph. /// - public interface IDependencyRecorder - { + public interface IDependencyRecorder { /// /// Reports a dependency detected by the linker. /// diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs index d4f610fbb533..6aa49124b883 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/ILogger.cs @@ -1,15 +1,12 @@ -using System; -namespace Mono.Linker -{ - public enum MessageImportance - { +using System; +namespace Mono.Linker { + public enum MessageImportance { High, Low, Normal, } - public interface ILogger - { - void LogMessage (MessageImportance importance, string message, params object[] values); + public interface ILogger { + void LogMessage (MessageImportance importance, string message, params object [] values); } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs index b3aae2b2ea78..a3b236a86dea 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/IReflectionPatternRecorder.cs @@ -1,4 +1,4 @@ -// +// // IReflectionPatternRecorder.cs // // Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com) @@ -25,8 +25,7 @@ using Mono.Cecil; -namespace Mono.Linker -{ +namespace Mono.Linker { /// /// Interface which is called every time the linker inspects a pattern of code involving reflection to determine a more complex /// dependency. @@ -38,8 +37,7 @@ namespace Mono.Linker /// - or it will call UnrecognizedReflectionAccessPattern with an optional message describing why it could not recognize /// the pattern. /// - public interface IReflectionPatternRecorder - { + public interface IReflectionPatternRecorder { /// /// Called when the linker recognized a reflection access pattern (and thus was able to correctly apply marking to the accessed item). /// diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs index 65c09f60fa1d..54c710cf93a4 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Inflater.cs @@ -5,102 +5,97 @@ namespace Mono.Linker { class Inflater { - public static TypeReference InflateType(GenericContext context, TypeReference typeReference) + public static TypeReference InflateType (GenericContext context, TypeReference typeReference) { - var typeDefinition = InflateTypeWithoutException(context, typeReference); - if (typeDefinition == null) - throw new InvalidOperationException($"Unable to resolve a reference to the type '{typeReference.FullName}' in the assembly '{typeReference.Module.Assembly.FullName}'. Does this type exist in a different assembly in the project?"); - + var typeDefinition = InflateTypeWithoutException (context, typeReference); + if (typeDefinition is null) + throw new InvalidOperationException ($"Unable to resolve a reference to the type '{typeReference.FullName}' in the assembly '{typeReference.Module.Assembly.FullName}'. Does this type exist in a different assembly in the project?"); + return typeDefinition; } - - public static GenericInstanceType InflateType(GenericContext context, TypeDefinition typeDefinition) + + public static GenericInstanceType InflateType (GenericContext context, TypeDefinition typeDefinition) { - return ConstructGenericType(context, typeDefinition, typeDefinition.GenericParameters); + return ConstructGenericType (context, typeDefinition, typeDefinition.GenericParameters); } - - public static GenericInstanceType InflateType(GenericContext context, GenericInstanceType genericInstanceType) + + public static GenericInstanceType InflateType (GenericContext context, GenericInstanceType genericInstanceType) { - var inflatedType = ConstructGenericType(context, genericInstanceType.Resolve(), genericInstanceType.GenericArguments); + var inflatedType = ConstructGenericType (context, genericInstanceType.Resolve (), genericInstanceType.GenericArguments); inflatedType.MetadataToken = genericInstanceType.MetadataToken; return inflatedType; } - - public static TypeReference InflateTypeWithoutException(GenericContext context, TypeReference typeReference) + + public static TypeReference InflateTypeWithoutException (GenericContext context, TypeReference typeReference) { var genericParameter = typeReference as GenericParameter; - if (genericParameter != null) - { - if (context.Method == null && genericParameter.Type != GenericParameterType.Type) - { + if (genericParameter is not null) { + if (context.Method is null && genericParameter.Type != GenericParameterType.Type) { // If no method is specified assume only partial inflation is desired. return typeReference; } - + var genericArgumentType = genericParameter.Type == GenericParameterType.Type - ? context.Type.GenericArguments[genericParameter.Position] - : context.Method.GenericArguments[genericParameter.Position]; - + ? context.Type.GenericArguments [genericParameter.Position] + : context.Method.GenericArguments [genericParameter.Position]; + var inflatedType = genericArgumentType; return inflatedType; } var genericInstanceType = typeReference as GenericInstanceType; - if (genericInstanceType != null) - return InflateType(context, genericInstanceType); - + if (genericInstanceType is not null) + return InflateType (context, genericInstanceType); + var arrayType = typeReference as ArrayType; - if (arrayType != null) - return new ArrayType(InflateType(context, arrayType.ElementType), arrayType.Rank); - + if (arrayType is not null) + return new ArrayType (InflateType (context, arrayType.ElementType), arrayType.Rank); + var byReferenceType = typeReference as ByReferenceType; - if (byReferenceType != null) - return new ByReferenceType(InflateType(context, byReferenceType.ElementType)); - + if (byReferenceType is not null) + return new ByReferenceType (InflateType (context, byReferenceType.ElementType)); + var pointerType = typeReference as PointerType; - if (pointerType != null) - return new PointerType(InflateType(context, pointerType.ElementType)); - + if (pointerType is not null) + return new PointerType (InflateType (context, pointerType.ElementType)); + var reqModType = typeReference as RequiredModifierType; - if (reqModType != null) - return InflateTypeWithoutException(context, reqModType.ElementType); - + if (reqModType is not null) + return InflateTypeWithoutException (context, reqModType.ElementType); + var optModType = typeReference as OptionalModifierType; - if (optModType != null) - return InflateTypeWithoutException(context, optModType.ElementType); - - return typeReference.Resolve(); + if (optModType is not null) + return InflateTypeWithoutException (context, optModType.ElementType); + + return typeReference.Resolve (); } - - static GenericInstanceType ConstructGenericType(GenericContext context, TypeDefinition typeDefinition, IEnumerable genericArguments) + + static GenericInstanceType ConstructGenericType (GenericContext context, TypeDefinition typeDefinition, IEnumerable genericArguments) { - var inflatedType = new GenericInstanceType(typeDefinition); - + var inflatedType = new GenericInstanceType (typeDefinition); + foreach (var genericArgument in genericArguments) - inflatedType.GenericArguments.Add(InflateType(context, genericArgument)); - + inflatedType.GenericArguments.Add (InflateType (context, genericArgument)); + return inflatedType; } - public class GenericContext - { + public class GenericContext { private readonly GenericInstanceType _type; private readonly GenericInstanceMethod _method; - public GenericContext(GenericInstanceType type, GenericInstanceMethod method) + public GenericContext (GenericInstanceType type, GenericInstanceMethod method) { _type = type; _method = method; } - public GenericInstanceType Type - { + public GenericInstanceType Type { get { return _type; } } - public GenericInstanceMethod Method - { + public GenericInstanceMethod Method { get { return _method; } } } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs index 02dcf6469ad4..7fc1023de6c2 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/KnownMembers.cs @@ -1,9 +1,7 @@ -using Mono.Cecil; +using Mono.Cecil; -namespace Mono.Linker -{ - public class KnownMembers - { +namespace Mono.Linker { + public class KnownMembers { public MethodDefinition NotSupportedExceptionCtorString { get; set; } public MethodDefinition DisablePrivateReflectionAttributeCtor { get; set; } public MethodDefinition ObjectCtor { get; set; } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs index 8d596844f727..d03dacb8aa25 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LinkContext.cs @@ -1,4 +1,4 @@ -// +// // LinkContext.cs // // Author: @@ -91,20 +91,17 @@ public bool LinkSymbols { set { _linkSymbols = value; } } - public bool KeepTypeForwarderOnlyAssemblies - { + public bool KeepTypeForwarderOnlyAssemblies { get { return _keepTypeForwarderOnlyAssemblies; } set { _keepTypeForwarderOnlyAssemblies = value; } } - public bool KeepMembersForDebugger - { + public bool KeepMembersForDebugger { get { return _keepMembersForDebugger; } set { _keepMembersForDebugger = value; } } - public bool IgnoreUnresolved - { + public bool IgnoreUnresolved { get { return _ignoreUnresolved; } set { _ignoreUnresolved = value; } } @@ -167,8 +164,7 @@ public LinkContext (Pipeline pipeline) } public LinkContext (Pipeline pipeline, AssemblyResolver resolver) - : this(pipeline, resolver, new ReaderParameters - { + : this (pipeline, resolver, new ReaderParameters { AssemblyResolver = resolver }, new UnintializedContextFactory ()) { @@ -182,10 +178,10 @@ public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParamete _actions = new Dictionary (); _parameters = new Dictionary (); _readerParameters = readerParameters; - + SymbolReaderProvider = new DefaultSymbolReaderProvider (false); - if (factory == null) + if (factory is null) throw new ArgumentNullException (nameof (factory)); _annotations = factory.CreateAnnotationStore (this); @@ -203,7 +199,7 @@ public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParamete public void AddSubstitutionFile (string file) { - if (Substitutions == null) { + if (Substitutions is null) { Substitutions = new List (); Substitutions.Add (file); return; @@ -222,7 +218,7 @@ public TypeDefinition GetType (string fullName) if (pos == -1) { foreach (AssemblyDefinition asm in GetAssemblies ()) { var type = asm.MainModule.GetType (fullName); - if (type != null) + if (type is not null) return type; } @@ -255,12 +251,11 @@ public AssemblyDefinition Resolve (IMetadataScope scope) try { AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters); - if (assembly != null) + if (assembly is not null) RegisterAssembly (assembly); return assembly; - } - catch (Exception e) { + } catch (Exception e) { throw new AssemblyResolutionException (reference, e); } } @@ -283,7 +278,7 @@ public virtual void SafeReadSymbols (AssemblyDefinition assembly) if (assembly.MainModule.HasSymbols) return; - if (_symbolReaderProvider == null) + if (_symbolReaderProvider is null) throw new ArgumentNullException (nameof (_symbolReaderProvider)); try { @@ -291,7 +286,7 @@ public virtual void SafeReadSymbols (AssemblyDefinition assembly) assembly.MainModule, assembly.MainModule.FileName); - if (symbolReader == null) + if (symbolReader is null) return; try { @@ -309,11 +304,11 @@ public virtual void SafeReadSymbols (AssemblyDefinition assembly) public virtual ICollection ResolveReferences (AssemblyDefinition assembly) { List references = new List (); - if (assembly == null) + if (assembly is null) return references; foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) { AssemblyDefinition definition = Resolve (reference); - if (definition != null) + if (definition is not null) references.Add (definition); } return references; @@ -330,7 +325,7 @@ static AssemblyNameReference GetReference (IMetadataScope scope) return reference; } - + public void SetAction (AssemblyDefinition assembly, AssemblyAction defaultAction) { RegisterAssembly (assembly); @@ -363,7 +358,7 @@ public static bool IsCore (AssemblyNameReference name) case "mscorlib": case "Accessibility": case "Mono.Security": - // WPF + // WPF case "PresentationFramework": case "PresentationCore": case "WindowsBase": @@ -372,7 +367,7 @@ public static bool IsCore (AssemblyNameReference name) case "PresentationUI": case "ReachFramework": case "netstandard": - return true; + return true; default: return name.Name.StartsWith ("System") || name.Name.StartsWith ("Microsoft"); @@ -411,7 +406,7 @@ public void Dispose () public bool IsFeatureExcluded (string featureName) { - return ExcludedFeatures != null && Array.IndexOf (ExcludedFeatures, featureName) >= 0; + return ExcludedFeatures is not null && Array.IndexOf (ExcludedFeatures, featureName) >= 0; } public bool IsOptimizationEnabled (CodeOptimizations optimization) @@ -426,16 +421,15 @@ public void LogMessage (string message) public void LogMessage (MessageImportance importance, string message) { - if (LogMessages && Logger != null) + if (LogMessages && Logger is not null) Logger.LogMessage (importance, "{0}", message); } } [Flags] - public enum CodeOptimizations - { + public enum CodeOptimizations { BeforeFieldInit = 1 << 0, - + /// /// Option to disable removal of overrides of virtual methods when a type is never instantiated /// @@ -443,7 +437,7 @@ public enum CodeOptimizations /// that do not get an instance constructor marked. /// OverrideRemoval = 1 << 1, - + /// /// Option to disable delaying marking of instance methods until an instance of that type could exist /// diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs index c4ca8f67e1d5..2b11298d3a21 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoadException.cs @@ -1,9 +1,7 @@ -using System; +using System; -namespace Mono.Linker -{ - public class LoadException : Exception - { +namespace Mono.Linker { + public class LoadException : Exception { public LoadException (string message) : base (message) { diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs index f9c0d89e938d..b64b1a792089 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/LoggingReflectionPatternRecorder.cs @@ -1,4 +1,4 @@ -// +// // LoggingReflectionPatternRecorder.cs // // Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com) @@ -25,10 +25,8 @@ using Mono.Cecil; -namespace Mono.Linker -{ - class LoggingReflectionPatternRecorder : IReflectionPatternRecorder - { +namespace Mono.Linker { + class LoggingReflectionPatternRecorder : IReflectionPatternRecorder { private readonly LinkContext _context; public LoggingReflectionPatternRecorder (LinkContext context) diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs index fd8d6057c346..7c84e5646386 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkException.cs @@ -1,11 +1,9 @@ -using System; +using System; using Mono.Cecil; -namespace Mono.Linker -{ - public class MarkException : Exception - { +namespace Mono.Linker { + public class MarkException : Exception { public MethodDefinition Method { get; private set; } public MarkException (string message) diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs index b477a5ce3896..4fa7ac0325a7 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MarkingHelpers.cs @@ -1,4 +1,4 @@ -using System; +using System; using Mono.Cecil; namespace Mono.Linker { diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs index 267a7c3ba6d2..ca726c63260f 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodBodyScanner.cs @@ -11,7 +11,7 @@ public static bool IsWorthConvertingToThrow (MethodBody body) // Some bodies are cheaper size wise to leave alone than to convert to a throw Instruction previousMeaningful = null; int meaningfulCount = 0; - foreach (var ins in body.Instructions) { + foreach (var ins in body.Instructions) { // Handle ignoring noops because because (1) it's a valid case to ignore // and (2) When running the tests on .net core roslyn tosses in no ops // and that leads to a difference in test results between mcs and .net framework csc. @@ -19,23 +19,23 @@ public static bool IsWorthConvertingToThrow (MethodBody body) continue; meaningfulCount++; - + if (meaningfulCount == 1 && ins.OpCode.Code == Code.Ret) return false; - if (meaningfulCount == 2 && ins.OpCode.Code == Code.Ret && previousMeaningful != null) { + if (meaningfulCount == 2 && ins.OpCode.Code == Code.Ret && previousMeaningful is not null) { if (previousMeaningful.OpCode.StackBehaviourPop == StackBehaviour.Pop0) { switch (previousMeaningful.OpCode.StackBehaviourPush) { - case StackBehaviour.Pushi: - case StackBehaviour.Pushi8: - case StackBehaviour.Pushr4: - case StackBehaviour.Pushr8: - return false; + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + return false; } - + switch (previousMeaningful.OpCode.Code) { - case Code.Ldnull: - return false; + case Code.Ldnull: + return false; } } } @@ -82,7 +82,7 @@ public static IEnumerable GetReferencedInterfaces (Anno static HashSet AllPossibleStackTypes (MethodDefinition method) { if (!method.HasBody) - throw new ArgumentException(); + throw new ArgumentException (); var body = method.Body; var types = new HashSet (); @@ -90,7 +90,7 @@ static HashSet AllPossibleStackTypes (MethodDefinition method) foreach (VariableDefinition var in body.Variables) AddIfResolved (types, var.VariableType); - foreach(var parameter in body.Method.Parameters) + foreach (var parameter in body.Method.Parameters) AddIfResolved (types, parameter.ParameterType); foreach (ExceptionHandler eh in body.ExceptionHandlers) { @@ -110,7 +110,7 @@ static HashSet AllPossibleStackTypes (MethodDefinition method) AddFromGenericInstance (types, genericInstanceType); var resolvedMethod = methodReference.Resolve (); - if (resolvedMethod != null) { + if (resolvedMethod is not null) { if (resolvedMethod.HasParameters) { foreach (var param in resolvedMethod.Parameters) AddIfResolved (types, param.ParameterType); @@ -157,9 +157,9 @@ static void AddFromGenericParameterProvider (HashSet set, IGener static void AddIfResolved (HashSet set, TypeReference item) { var resolved = item?.Resolve (); - if (resolved == null) + if (resolved is null) return; set.Add (resolved); } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs index b2b066727808..cc1d5b6896ee 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodDefinitionExtensions.cs @@ -1,9 +1,7 @@ -using Mono.Cecil; +using Mono.Cecil; -namespace Mono.Linker -{ - public static class MethodDefinitionExtensions - { +namespace Mono.Linker { + public static class MethodDefinitionExtensions { public static bool IsDefaultConstructor (this MethodDefinition method) { return IsInstanceConstructor (method) && !method.HasParameters; @@ -81,13 +79,13 @@ public static bool IsFinalizer (this MethodDefinition method) return true; } - + public static void ClearDebugInformation (this MethodDefinition method) { // TODO: This always allocates, update when Cecil catches up var di = method.DebugInformation; di.SequencePoints.Clear (); - if (di.Scope != null) { + if (di.Scope is not null) { di.Scope.Variables.Clear (); di.Scope.Constants.Clear (); di.Scope = null; diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs index 23558db44dcf..4b9c599fc3d4 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/MethodReferenceExtensions.cs @@ -1,15 +1,13 @@ -using System; +using System; using Mono.Cecil; -namespace Mono.Linker -{ - public static class MethodReferenceExtensions - { +namespace Mono.Linker { + public static class MethodReferenceExtensions { public static TypeReference GetReturnType (this MethodReference method) { var genericInstance = method.DeclaringType as GenericInstanceType; - if (genericInstance != null) + if (genericInstance is not null) return TypeReferenceExtensions.InflateGenericType (genericInstance, method.ReturnType); return method.ReturnType; @@ -19,7 +17,7 @@ public static TypeReference GetParameterType (this MethodReference method, int p { var genericInstance = method.DeclaringType as GenericInstanceType; - if (genericInstance != null) + if (genericInstance is not null) return TypeReferenceExtensions.InflateGenericType (genericInstance, method.Parameters [parameterIndex].ParameterType); return method.Parameters [parameterIndex].ParameterType; diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs index a406625fa315..d6c25ff3f7ef 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OutputException.cs @@ -1,9 +1,7 @@ -using System; +using System; -namespace Mono.Linker -{ - public class OutputException : Exception - { +namespace Mono.Linker { + public class OutputException : Exception { public OutputException (string message) : base (message) { @@ -14,4 +12,4 @@ public OutputException (string message, Exception innerException) { } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs index f73d8bc1c63c..b9a5448b37c5 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/OverrideInformation.cs @@ -15,29 +15,25 @@ public OverrideInformation (MethodDefinition @base, MethodDefinition @override, MatchingInterfaceImplementation = matchingInterfaceImplementation; } - public bool IsOverrideOfInterfaceMember - { - get - { - if (MatchingInterfaceImplementation != null) + public bool IsOverrideOfInterfaceMember { + get { + if (MatchingInterfaceImplementation is not null) return true; return Base.DeclaringType.IsInterface; } } - public TypeDefinition InterfaceType - { - get - { + public TypeDefinition InterfaceType { + get { if (!IsOverrideOfInterfaceMember) return null; - if (MatchingInterfaceImplementation != null) + if (MatchingInterfaceImplementation is not null) return MatchingInterfaceImplementation.InterfaceType.Resolve (); return Base.DeclaringType; } } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs index a28de3ba1b24..e9334be89fbb 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Pipeline.cs @@ -1,4 +1,4 @@ -// +// // Pipeline.cs // // Author: @@ -39,7 +39,7 @@ public class Pipeline { public Pipeline () { - _steps = new List(); + _steps = new List (); } public void PrependStep (IStep step) @@ -127,7 +127,7 @@ public void Process (LinkContext context) _steps.Remove (step); } } - + protected virtual void ProcessStep (LinkContext context, IStep step) { context.Tracer.Push (step); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs index 1a6b7109fe93..cadbc27aaeae 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/Tracer.cs @@ -1,4 +1,4 @@ -// +// // Tracer.cs // // Author: @@ -29,10 +29,8 @@ using System; using System.Collections.Generic; -namespace Mono.Linker -{ - public class Tracer - { +namespace Mono.Linker { + public class Tracer { protected readonly LinkContext context; Stack dependency_stack; @@ -47,7 +45,7 @@ public Tracer (LinkContext context) public void Finish () { dependency_stack = null; - if (recorders != null) { + if (recorders is not null) { foreach (var recorder in recorders) { if (recorder is IDisposable disposableRecorder) disposableRecorder.Dispose (); @@ -59,7 +57,7 @@ public void Finish () public void AddRecorder (IDependencyRecorder recorder) { - if (recorders == null) { + if (recorders is null) { recorders = new List (); } @@ -87,7 +85,7 @@ public void Pop () bool IsRecordingEnabled () { - return recorders != null; + return recorders is not null; } public void AddDirectDependency (object b, object e) diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs index 1e06def6eb68..40c94f88a7de 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeDefinitionExtensions.cs @@ -29,8 +29,8 @@ public static TypeReference GetEnumUnderlyingType (this TypeDefinition enumType) } throw new MissingFieldException ($"Enum type '{enumType.FullName}' is missing 'value__' field"); - } - + } + public static bool IsMulticastDelegate (this TypeDefinition td) { return td.BaseType?.Name == "MulticastDelegate" && td.BaseType.Namespace == "System"; @@ -41,4 +41,4 @@ public static bool IsSerializable (this TypeDefinition td) return (td.Attributes & TypeAttributes.Serializable) != 0; } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs index 15d53c09c6a1..1a86b9b4144e 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeNameParser.cs @@ -1,8 +1,9 @@ -using System; +using System; namespace Mono.Linker { public static class TypeNameParser { - public static bool TryParseTypeAssemblyQualifiedName (string value, out string typeName, out string assemblyName) { + public static bool TryParseTypeAssemblyQualifiedName (string value, out string typeName, out string assemblyName) + { if (string.IsNullOrEmpty (value)) { typeName = null; assemblyName = null; @@ -19,7 +20,7 @@ public static bool TryParseTypeAssemblyQualifiedName (string value, out string t while (value.IndexOf ('[') > 0) { var openidx = value.IndexOf ('['); var closeidx = value.IndexOf (']'); - + // No matching close ] or out of order if (closeidx < 0 || closeidx < openidx) { typeName = null; @@ -45,4 +46,4 @@ public static bool TryParseTypeAssemblyQualifiedName (string value, out string t return true; } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs index bc743c65a188..83c0635fc6e7 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypePreserve.cs @@ -28,8 +28,7 @@ namespace Mono.Linker { - public enum TypePreserve - { + public enum TypePreserve { Nothing, // This is actually Declaration All, Fields, diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs index ae271a0d4f7e..262faa106421 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/TypeReferenceExtensions.cs @@ -1,38 +1,36 @@ -using System; +using System; using Mono.Cecil; using System.Collections.Generic; using System.Linq; -namespace Mono.Linker -{ - public static class TypeReferenceExtensions - { +namespace Mono.Linker { + public static class TypeReferenceExtensions { public static TypeReference GetInflatedBaseType (this TypeReference type) { - if (type == null) + if (type is null) return null; if (type.IsGenericParameter || type.IsByReference || type.IsPointer) return null; var sentinelType = type as SentinelType; - if (sentinelType != null) + if (sentinelType is not null) return sentinelType.ElementType.GetInflatedBaseType (); var pinnedType = type as PinnedType; - if (pinnedType != null) + if (pinnedType is not null) return pinnedType.ElementType.GetInflatedBaseType (); var requiredModifierType = type as RequiredModifierType; - if (requiredModifierType != null) + if (requiredModifierType is not null) return requiredModifierType.ElementType.GetInflatedBaseType (); var genericInstance = type as GenericInstanceType; - if (genericInstance != null) { + if (genericInstance is not null) { var baseType = type.Resolve ()?.BaseType; var baseTypeGenericInstance = baseType as GenericInstanceType; - if (baseTypeGenericInstance != null) + if (baseTypeGenericInstance is not null) return InflateGenericType (genericInstance, baseType); return baseType; @@ -49,7 +47,7 @@ public static IEnumerable GetInflatedInterfaces (this TypeReferen yield break; var genericInstance = typeRef as GenericInstanceType; - if (genericInstance != null) { + if (genericInstance is not null) { foreach (var interfaceImpl in typeDef.Interfaces) yield return InflateGenericType (genericInstance, interfaceImpl.InterfaceType); } else { @@ -61,7 +59,7 @@ public static IEnumerable GetInflatedInterfaces (this TypeReferen public static TypeReference InflateGenericType (GenericInstanceType genericInstanceProvider, TypeReference typeToInflate) { var arrayType = typeToInflate as ArrayType; - if (arrayType != null) { + if (arrayType is not null) { var inflatedElementType = InflateGenericType (genericInstanceProvider, arrayType.ElementType); if (inflatedElementType != arrayType.ElementType) @@ -71,11 +69,11 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var genericInst = typeToInflate as GenericInstanceType; - if (genericInst != null) + if (genericInst is not null) return MakeGenericType (genericInstanceProvider, genericInst); var genericParameter = typeToInflate as GenericParameter; - if (genericParameter != null) { + if (genericParameter is not null) { if (genericParameter.Owner is MethodReference) return genericParameter; @@ -85,12 +83,12 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var functionPointerType = typeToInflate as FunctionPointerType; - if (functionPointerType != null) { + if (functionPointerType is not null) { var result = new FunctionPointerType (); result.ReturnType = InflateGenericType (genericInstanceProvider, functionPointerType.ReturnType); for (int i = 0; i < functionPointerType.Parameters.Count; i++) { - var inflatedParameterType = InflateGenericType(genericInstanceProvider, functionPointerType.Parameters [i].ParameterType); + var inflatedParameterType = InflateGenericType (genericInstanceProvider, functionPointerType.Parameters [i].ParameterType); result.Parameters.Add (new ParameterDefinition (inflatedParameterType)); } @@ -98,7 +96,7 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var modifierType = typeToInflate as IModifierType; - if (modifierType != null) { + if (modifierType is not null) { var modifier = InflateGenericType (genericInstanceProvider, modifierType.ModifierType); var elementType = InflateGenericType (genericInstanceProvider, modifierType.ElementType); @@ -110,7 +108,7 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var pinnedType = typeToInflate as PinnedType; - if (pinnedType != null) { + if (pinnedType is not null) { var elementType = InflateGenericType (genericInstanceProvider, pinnedType.ElementType); if (elementType != pinnedType.ElementType) @@ -120,7 +118,7 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var pointerType = typeToInflate as PointerType; - if (pointerType != null) { + if (pointerType is not null) { var elementType = InflateGenericType (genericInstanceProvider, pointerType.ElementType); if (elementType != pointerType.ElementType) @@ -130,7 +128,7 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var byReferenceType = typeToInflate as ByReferenceType; - if (byReferenceType != null) { + if (byReferenceType is not null) { var elementType = InflateGenericType (genericInstanceProvider, byReferenceType.ElementType); if (elementType != byReferenceType.ElementType) @@ -140,7 +138,7 @@ public static TypeReference InflateGenericType (GenericInstanceType genericInsta } var sentinelType = typeToInflate as SentinelType; - if (sentinelType != null) { + if (sentinelType is not null) { var elementType = InflateGenericType (genericInstanceProvider, sentinelType.ElementType); if (elementType != sentinelType.ElementType) @@ -171,7 +169,7 @@ public static IEnumerable GetMethods (this TypeReference type) yield break; var genericInstanceType = type as GenericInstanceType; - if (genericInstanceType != null) { + if (genericInstanceType is not null) { foreach (var methodDef in typeDef.Methods) yield return MakeMethodReferenceForGenericInstanceType (genericInstanceType, methodDef); } else { @@ -189,7 +187,7 @@ private static MethodReference MakeMethodReferenceForGenericInstanceType (Generi }; foreach (var parameter in methodDef.Parameters) - method.Parameters.Add (new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); + method.Parameters.Add (new ParameterDefinition (parameter.Name, parameter.Attributes, parameter.ParameterType)); foreach (var gp in methodDef.GenericParameters) method.GenericParameters.Add (new GenericParameter (gp.Name, method)); @@ -215,7 +213,7 @@ public static bool HasDefaultConstructor (this TypeReference type) return false; } - + public static MethodReference GetDefaultInstanceConstructor (this TypeReference type) { foreach (var m in type.GetMethods ()) { diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs index 4c96fc283693..95a076389429 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XApiReader.cs @@ -1,4 +1,4 @@ -// +// // XApiReader.cs // // Author: @@ -122,7 +122,7 @@ void OnClass (XPathNavigator nav) string name = GetClassName (nav); TypeDefinition type = _assembly.MainModule.GetType (name); - if (type == null) + if (type is null) return; _visitor.OnClass (nav, type); @@ -159,7 +159,7 @@ void OnField (XPathNavigator nav) TypeDefinition declaring = PeekType (); FieldDefinition field = declaring.Fields.FirstOrDefault (f => f.Name == GetName (nav)); - if (field != null) + if (field is not null) _visitor.OnField (nav, field); ProcessAttributes (nav); @@ -170,7 +170,7 @@ void OnInterface (XPathNavigator nav) string name = GetName (nav); TypeDefinition type = _context.GetType (GetTypeName (name)); - if (type != null) + if (type is not null) _visitor.OnInterface (nav, type); } @@ -183,7 +183,7 @@ void OnMethod (XPathNavigator nav) string signature = GetMethodSignature (); MethodDefinition method = GetMethod (signature); - if (method != null) + if (method is not null) _visitor.OnMethod (nav, method); ProcessAttributes (nav); @@ -219,7 +219,7 @@ void InitMethodSignature (XPathNavigator nav) _signature = new StringBuilder (); string returntype = GetAttribute (nav, "returntype"); - if (returntype == null || returntype.Length == 0) + if (returntype is null || returntype.Length == 0) returntype = "System.Void"; _signature.Append (NormalizeTypeName (returntype)); @@ -276,7 +276,7 @@ void OnConstructor (XPathNavigator nav) string signature = GetMethodSignature (); MethodDefinition ctor = GetMethod (signature); - if (ctor != null) + if (ctor is not null) _visitor.OnConstructor (nav, ctor); ProcessAttributes (nav); @@ -288,7 +288,7 @@ void OnProperty (XPathNavigator nav) TypeDefinition type = PeekType (); var property = type.Properties.FirstOrDefault (p => p.Name == name); - if (property != null) + if (property is not null) _visitor.OnProperty (nav, property); ProcessAttributes (nav); @@ -301,7 +301,7 @@ void OnEvent (XPathNavigator nav) TypeDefinition type = PeekType (); EventDefinition evt = type.Events.FirstOrDefault (e => e.Name == name); - if (evt != null) + if (evt is not null) _visitor.OnEvent (nav, evt); ProcessAttributes (nav); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs index 637b94c2aa1b..87d32b8d8bda 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/linker/Linker/XmlDependencyRecorder.cs @@ -1,4 +1,4 @@ -// +// // Tracer.cs // // Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com) @@ -30,13 +30,11 @@ using System.IO.Compression; using System.Xml; -namespace Mono.Linker -{ +namespace Mono.Linker { /// /// Class which implements IDependencyRecorder and writes the dependencies into an XML file. /// - public class XmlDependencyRecorder : IDependencyRecorder, IDisposable - { + public class XmlDependencyRecorder : IDependencyRecorder, IDisposable { public const string DefaultDependenciesFileName = "linker-dependencies.xml.gz"; private readonly LinkContext context; @@ -52,7 +50,7 @@ public XmlDependencyRecorder (LinkContext context, string fileName = null) IndentChars = "\t" }; - if (fileName == null) + if (fileName is null) fileName = DefaultDependenciesFileName; if (string.IsNullOrEmpty (Path.GetDirectoryName (fileName)) && !string.IsNullOrEmpty (context.OutputDirectory)) { @@ -77,7 +75,7 @@ public XmlDependencyRecorder (LinkContext context, string fileName = null) public void Dispose () { - if (writer == null) + if (writer is null) return; writer.WriteEndElement (); @@ -125,21 +123,21 @@ static bool IsAssemblyBound (TypeDefinition td) return true; td = td.DeclaringType; - } while (td != null); + } while (td is not null); return false; } string TokenString (object o) { - if (o == null) + if (o is null) return "N:null"; if (o is TypeReference t) { bool addAssembly = true; var td = t as TypeDefinition ?? t.Resolve (); - if (td != null) { + if (td is not null) { addAssembly = td.IsNotPublic || IsAssemblyBound (td); t = td; } @@ -158,12 +156,12 @@ string TokenString (object o) bool WillAssemblyBeModified (AssemblyDefinition assembly) { switch (context.Annotations.GetAction (assembly)) { - case AssemblyAction.Link: - case AssemblyAction.AddBypassNGen: - case AssemblyAction.AddBypassNGenUsed: - return true; - default: - return false; + case AssemblyAction.Link: + case AssemblyAction.AddBypassNGen: + case AssemblyAction.AddBypassNGenUsed: + return true; + default: + return false; } } @@ -182,7 +180,7 @@ bool ShouldRecord (object o) var resolved = typeRef.Resolve (); // Err on the side of caution if we can't resolve - if (resolved == null) + if (resolved is null) return true; return WillAssemblyBeModified (resolved.Module.Assembly); @@ -192,7 +190,7 @@ bool ShouldRecord (object o) var resolved = mRef.Resolve (); // Err on the side of caution if we can't resolve - if (resolved == null) + if (resolved is null) return true; return WillAssemblyBeModified (resolved.DeclaringType.Module.Assembly); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs index 6a910a9d97fb..942907d00fde 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/ApplyPreserveAttributeBase.cs @@ -65,13 +65,13 @@ public override void ProcessEvent (EventDefinition @event) void MarkMethodIfPreserved (MethodDefinition method) { - foreach (var attribute in GetPreserveAttributes (method)) + foreach (var attribute in GetPreserveAttributes (method)) MarkMethod (method, attribute); } void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute) { - if (method == null) + if (method is null) return; Mark (method, preserve_attribute); @@ -91,7 +91,7 @@ void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute) void PreserveConditional (IMetadataTokenProvider provider) { var method = provider as MethodDefinition; - if (method == null) { + if (method is null) { // workaround to support (uncommon but valid) conditional fields form [Preserve] PreserveUnconditional (provider); return; @@ -102,7 +102,7 @@ void PreserveConditional (IMetadataTokenProvider provider) static bool IsConditionalAttribute (CustomAttribute attribute) { - if (attribute == null) + if (attribute is null) return false; foreach (var named_argument in attribute.Fields) @@ -117,7 +117,7 @@ void PreserveUnconditional (IMetadataTokenProvider provider) Annotations.Mark (provider); var member = provider as IMemberDefinition; - if (member == null || member.DeclaringType == null) + if (member is null || member.DeclaringType is null) return; Mark (member.DeclaringType, null); @@ -130,9 +130,9 @@ void TryApplyPreserveAttribute (TypeDefinition type) if (!attribute.HasFields) continue; - + foreach (var named_argument in attribute.Fields) - if (named_argument.Name == "AllMembers" && (bool)named_argument.Argument.Value) + if (named_argument.Name == "AllMembers" && (bool) named_argument.Argument.Value) Annotations.SetPreserve (type, TypePreserve.All); } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs index 69958598dda2..6d2abeef6e04 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CecilRocks.cs @@ -70,7 +70,7 @@ public static MethodDefinition GetTypeConstructor (this TypeDefinition self) public static void SimplifyMacros (this MethodBody self) { - if (self == null) + if (self is null) throw new ArgumentNullException ("self"); foreach (var instruction in self.Instructions) { @@ -225,7 +225,7 @@ static void MakeMacro (Instruction instruction, OpCode opcode) public static void OptimizeMacros (this MethodBody self) { - if (self == null) + if (self is null) throw new ArgumentNullException ("self"); var method = self.Method; @@ -456,14 +456,14 @@ public static ParameterDefinition GetParameter (this MethodBody self, int index) public static bool Implements (this TypeReference self, string interfaceName) { - if (interfaceName == null) + if (interfaceName is null) throw new ArgumentNullException ("interfaceName"); - if (self == null) + if (self is null) return false; TypeDefinition type = self.Resolve (); - if (type == null) - return false; // not enough information available + if (type is null) + return false; // not enough information available // special case, check if we implement ourselves if (type.IsInterface && (type.FullName == interfaceName)) @@ -474,7 +474,7 @@ public static bool Implements (this TypeReference self, string interfaceName) public static bool Implements (TypeDefinition type, string interfaceName, bool generic) { - while (type != null) { + while (type is not null) { // does the type implements it itself if (type.HasInterfaces) { foreach (var iface in type.Interfaces) { @@ -487,30 +487,30 @@ public static bool Implements (TypeDefinition type, string interfaceName, bool g } } - type = type.BaseType != null ? type.BaseType.Resolve () : null; + type = type.BaseType is not null ? type.BaseType.Resolve () : null; } return false; } public static bool Inherits (this TypeReference self, string @namespace, string name) { - if (@namespace == null) + if (@namespace is null) throw new ArgumentNullException ("namespace"); - if (name == null) + if (name is null) throw new ArgumentNullException ("name"); - if (self == null) + if (self is null) return false; - + TypeReference current = self.Resolve (); - while (current != null) { + while (current is not null) { if (current.Is (@namespace, name)) return true; if (current.Is ("System", "Object")) return false; - + TypeDefinition td = current.Resolve (); - if (td == null) - return false; // could not resolve type + if (td is null) + return false; // could not resolve type current = td.BaseType; } return false; diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs index 1bb6d6fb0e14..38e2ad97fbf4 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/CustomizeActions.cs @@ -47,7 +47,7 @@ protected virtual bool IsLinkerSafeAttribute (CustomAttribute attribute) return (attribute.AttributeType.Name == "LinkerSafeAttribute"); } - const ModuleAttributes Supported = ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit | + const ModuleAttributes Supported = ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit | ModuleAttributes.Preferred32Bit | ModuleAttributes.StrongNameSigned; protected virtual bool IsSkipped (AssemblyDefinition assembly) @@ -74,7 +74,7 @@ protected virtual bool IsLinked (AssemblyDefinition assembly) if (Profile.IsSdkAssembly (assembly)) return true; if (Profile.IsProductAssembly (assembly)) - return true; + return true; // the assembly can be marked with [LinkAssembly] if (assembly.HasCustomAttributes) { foreach (var ca in assembly.CustomAttributes) { diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs index be1674044082..e10c7b6c6f91 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Dispatcher.cs @@ -110,19 +110,19 @@ public void Process (LinkContext context) void Push (ISubStep subStep) { - if (tracer != null) + if (tracer is not null) tracer.Push (subStep); } void Pop () { - if (tracer != null) + if (tracer is not null) tracer.Pop (); } static bool HasSubSteps (List substeps) { - return substeps != null && substeps.Count > 0; + return substeps is not null && substeps.Count > 0; } void BrowseAssemblies (IEnumerable assemblies) @@ -286,7 +286,7 @@ static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List< if (!Targets (substep, target)) return; - if (list == null) + if (list is null) list = new List (); list.Add (substep); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs index 3e3b312133b6..23ba6dc0ac87 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Extensions.cs @@ -12,7 +12,7 @@ public static partial class Extensions { public static bool TryGetLinkedAssembly (this LinkContext context, string name, out AssemblyDefinition assembly) { assembly = GetAssembly (context, name); - if (assembly == null) + if (assembly is null) return false; return context.Annotations.GetAction (assembly) == AssemblyAction.Link; @@ -30,7 +30,7 @@ public static AssemblyDefinition GetAssembly (this LinkContext context, string a // note: direct check, no inheritance public static bool Is (this TypeReference type, string @namespace, string name) { - return ((type != null) && (type.Name == name) && (type.Namespace == @namespace)); + return ((type is not null) && (type.Name == name) && (type.Namespace == @namespace)); } } } diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs index 18dbe7ff2514..5e9d3ee0726b 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveCrypto.cs @@ -82,11 +82,11 @@ void ProcessSystemCore (LinkContext context) bool TryAddPreserveInfo (AssemblyDefinition assembly, string name, string type) { var marker = GetCryptoType (assembly, name); - if (marker == null) + if (marker is null) return false; var implementation = GetCryptoType (assembly, type); - if (implementation == null) + if (implementation is null) return false; Preserve (marker, implementation); @@ -96,11 +96,11 @@ bool TryAddPreserveInfo (AssemblyDefinition assembly, string name, string type) void AddPreserveInfo (AssemblyDefinition assembly, string name, string type) { var marker = GetCryptoType (assembly, name); - if (marker == null) + if (marker is null) throw new ArgumentException (name); var implementation = GetCryptoType (assembly, type); - if (implementation == null) + if (implementation is null) throw new ArgumentException (type); Preserve (marker, implementation); @@ -108,7 +108,7 @@ void AddPreserveInfo (AssemblyDefinition assembly, string name, string type) void Preserve (TypeDefinition marker, TypeDefinition implementation) { - if (marker == null || implementation == null) + if (marker is null || implementation is null) return; foreach (var constructor in implementation.GetConstructors ()) annotations.AddPreservedMethod (marker, constructor); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs index bdb04a94db23..ee486cae93d8 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/PreserveSoapHttpClients.cs @@ -87,4 +87,4 @@ static bool IsWebServiceClient (TypeDefinition type) return type.Inherits ("System.Web.Services.Protocols", "SoapHttpClientProtocol"); } } -} \ No newline at end of file +} diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs index 54cfffa64f18..9cfbf9f0942c 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/Profile.cs @@ -11,19 +11,19 @@ public abstract class Profile { public static Profile Current { get { - if (current != null) + if (current is not null) return current; current = CreateProfile ("MonoTouch"); - if (current != null) + if (current is not null) return current; current = CreateProfile ("MonoDroid"); - if (current != null) + if (current is not null) return current; current = CreateProfile ("MonoMac"); - if (current != null) + if (current is not null) return current; throw new NotSupportedException ("No active profile"); @@ -36,7 +36,7 @@ public static Profile Current { static Profile CreateProfile (string name) { var type = Type.GetType (string.Format ("{0}.Tuner.{0}Profile", name)); - if (type == null) + if (type is null) return null; return (Profile) Activator.CreateInstance (type); @@ -66,7 +66,7 @@ protected virtual bool IsSdk (AssemblyDefinition assembly) { return IsSdk (assembly.Name.Name); } - + protected virtual bool IsProduct (AssemblyDefinition assembly) { return IsProduct (assembly.Name.Name); diff --git a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs index 19c638615da5..803b1e76bf1a 100644 --- a/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs +++ b/builds/mono-ios-sdk-destdir/ios-sources/external/linker/src/tuner/Mono.Tuner/RemoveResources.cs @@ -30,11 +30,11 @@ public virtual void Process (LinkContext context) for (int i = 0; i < resources.Count; i++) { var resource = resources [i] as EmbeddedResource; - if (resource == null) + if (resource is null) continue; if (RemoveResource (resource.Name)) - resources.RemoveAt(i--); + resources.RemoveAt (i--); } } @@ -47,9 +47,9 @@ bool RemoveResource (string name) case "collation.tailoring.bin": return false; default: - if (!name.Contains("cjk")) + if (!name.Contains ("cjk")) return false; - if (IncludeCJK()) + if (IncludeCJK ()) return false; return true; } From 667326ec1b32ec46f422b378f47a880863fa7cf0 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 27 Sep 2024 11:25:21 +0200 Subject: [PATCH 4/4] More cleanup --- tools/devops/automation/templates/tests/run-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml index ada31af1f8b1..057339f9a38a 100644 --- a/tools/devops/automation/templates/tests/run-tests.yml +++ b/tools/devops/automation/templates/tests/run-tests.yml @@ -147,7 +147,6 @@ steps: # show environment env -0 | sort -z | tr '\0' '\n' || true - make -C builds download -j make -C tests ${{ parameters.makeTarget }} # We reached the end! This means we succeeded!