Skip to content

Commit

Permalink
[dotnet] Prevent linking out code referenced by P/Invoke (dotnet#10182)
Browse files Browse the repository at this point in the history
* [dotnet] Generate references.mm to prevent linking out code referenced by P/Invoke

* Address PR feedback: Namespaces.Foundation -> "Foundation."

* Address PR feedback: Simplify hasSymbols

* Reuse ListExportedSymbols step, respect App.SymbolMode

* Address PR feedback

* Workaround for tvOS
  • Loading branch information
filipnavara authored Dec 3, 2020
1 parent 14e3282 commit 17722de
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 3 deletions.
13 changes: 12 additions & 1 deletion dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,14 @@
<ReadItemsFromFile File="$(_LinkerItemsDirectory)/_RegistrarFile.items" Condition="Exists('$(_LinkerItemsDirectory)/_RegistrarFile.items')">
<Output TaskParameter="Items" ItemName="_RegistrarFile" />
</ReadItemsFromFile>
<!-- Load _ReferencesFile -->
<ReadItemsFromFile File="$(_LinkerItemsDirectory)/_ReferencesFile.items" Condition="Exists('$(_LinkerItemsDirectory)/_ReferencesFile.items')">
<Output TaskParameter="Items" ItemName="_ReferencesFile" />
</ReadItemsFromFile>
<!-- Load _ReferencesLinkerFlags -->
<ReadItemsFromFile File="$(_LinkerItemsDirectory)/_ReferencesLinkerFlags.items" Condition="Exists('$(_LinkerItemsDirectory)/_ReferencesLinkerFlags.items')">
<Output TaskParameter="Items" ItemName="_ReferencesLinkerFlags" />
</ReadItemsFromFile>

<ItemGroup>
<_AssembliesToAOT Include="@(ResolvedFileToPublish)" Condition="'%(Extension)' == '.dll' Or '%(Extension)' == '.exe' " />
Expand Down Expand Up @@ -467,6 +475,9 @@
<_CompileNativeExecutableFile Include="@(_RegistrarFile)">
<OutputFile>$(_IntermediateNativeLibraryDir)%(Filename).o</OutputFile>
</_CompileNativeExecutableFile>
<_CompileNativeExecutableFile Include="@(_ReferencesFile)">
<OutputFile>$(_IntermediateNativeLibraryDir)%(Filename).o</OutputFile>
</_CompileNativeExecutableFile>
<_XamarinMainIncludeDirectory Include="$(_XamarinIncludeDirectory)" />
</ItemGroup>
</Target>
Expand Down Expand Up @@ -570,7 +581,7 @@
DylibRPath="$(_DylibRPath)"
EntitlementsInExecutable="$(_CompiledEntitlements)"
Frameworks="@(_NativeExecutableFrameworks);@(_BindingLibraryFrameworks)"
LinkerFlags="@(_BindingLibraryLinkerFlags);@(_MainLinkerFlags)"
LinkerFlags="@(_BindingLibraryLinkerFlags);@(_ReferencesLinkerFlags);@(_MainLinkerFlags)"
LinkWithLibraries="@(_XamarinMainLibraries);@(_BindingLibraryLinkWith);@(_MainLinkWith)"
MinimumOSVersion="$(_MinimumOSVersion)"
ObjectFiles="@(_NativeExecutableObjectFiles)"
Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/SetupStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,12 @@ protected override void TryProcess ()
post_sweep_substeps.Add (new RemoveAttributesStep ());
}

Steps.Add (new ListExportedSymbols (null));
Steps.Add (new LoadNonSkippedAssembliesStep ());
Steps.Add (new ExtractBindingLibrariesStep ());
Steps.Add (new RegistrarStep ());
Steps.Add (new GenerateMainStep ());
Steps.Add (new GenerateReferencesStep ());
Steps.Add (new GatherFrameworksStep ());

Configuration.Write ();
Expand Down
48 changes: 48 additions & 0 deletions tools/dotnet-linker/Steps/GenerateReferencesStep.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.IO;
using System.Text;

using Mono.Cecil;

using Xamarin.Bundler;
using Xamarin.Linker;

namespace Xamarin {

public class GenerateReferencesStep : ConfigurationAwareStep {
protected override string Name { get; } = "Generate References";
protected override int ErrorCode { get; } = 2320;

protected override void TryEndProcess ()
{
base.TryEndProcess ();

var app = Configuration.Application;
var required_symbols = Configuration.DerivedLinkContext.RequiredSymbols;
var items = new List<MSBuildItem> ();

switch (app.SymbolMode) {
case SymbolMode.Ignore:
break;
case SymbolMode.Code:
string reference_m = Path.Combine (Configuration.CacheDirectory, "reference.m");
reference_m = Configuration.Target.GenerateReferencingSource (reference_m, required_symbols);
if (!string.IsNullOrEmpty (reference_m)) {
var item = new MSBuildItem { Include = reference_m };
items.Add (item);
}
Configuration.WriteOutputForMSBuild ("_ReferencesFile", items);
break;
case SymbolMode.Linker:
foreach (var symbol in required_symbols) {
var item = new MSBuildItem { Include = "-u" + symbol.Prefix + symbol.Name };
items.Add (item);
}
Configuration.WriteOutputForMSBuild ("_ReferencesLinkerFlags", items);
break;
default:
throw ErrorHelper.CreateError (99, Errors.MX0099, $"invalid symbol mode: {app.SymbolMode}");
}
}
}
}
3 changes: 3 additions & 0 deletions tools/dotnet-linker/dotnet-linker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@
<Compile Include="..\linker\MonoTouch.Tuner\Extensions.cs">
<Link>external\tools\linker\MonoTouch.Tuner\Extensions.cs</Link>
</Compile>
<Compile Include="..\linker\MonoTouch.Tuner\ListExportedSymbols.cs">
<Link>external\tools\linker\MonoTouch.Tuner\ListExportedSymbols.cs</Link>
</Compile>
<Compile Include="..\linker\MonoTouch.Tuner\PreserveSmartEnumConversionsSubStep.cs">
<Link>external\tools\linker\MonoTouch.Tuner\PreserveSmartEnumConversionsSubStep.cs</Link>
</Compile>
Expand Down
17 changes: 15 additions & 2 deletions tools/linker/MonoTouch.Tuner/ListExportedSymbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
using Xamarin.Bundler;
using Xamarin.Linker;
using Xamarin.Tuner;
using Xamarin.Utils;

namespace MonoTouch.Tuner
namespace Xamarin.Linker.Steps
{
public class ListExportedSymbols : BaseStep
{
Expand All @@ -19,7 +20,11 @@ public class ListExportedSymbols : BaseStep

public DerivedLinkContext DerivedLinkContext {
get {
#if NET
return LinkerConfiguration.GetInstance (Context).DerivedLinkContext;
#else
return (DerivedLinkContext) Context;
#endif
}
}

Expand All @@ -36,8 +41,10 @@ protected override void ProcessAssembly (AssemblyDefinition assembly)
if (Annotations.GetAction (assembly) == AssemblyAction.Delete)
return;

#if !NET
if (skip_sdk_assemblies && Profile.IsSdkAssembly (assembly))
return;
#endif

if (!assembly.MainModule.HasTypes)
return;
Expand Down Expand Up @@ -116,8 +123,14 @@ void ProcessMethod (MethodDefinition method)
case "__Internal":
DerivedLinkContext.RequiredSymbols.AddFunction (pinfo.EntryPoint).AddMember (method);
break;
case "System.Native":

case "System.Net.Security.Native":
#if NET
if (DerivedLinkContext.App.Platform == ApplePlatform.TVOS)
break; // tvOS does not ship with System.Net.Security.Native due to https://github.com/dotnet/runtime/issues/45535
goto case "System.Native";
#endif
case "System.Native":
case "System.Security.Cryptography.Native.Apple":
DerivedLinkContext.RequireMonoNative = true;
DerivedLinkContext.RequiredSymbols.AddFunction (pinfo.EntryPoint).AddMember (method);
Expand Down

0 comments on commit 17722de

Please sign in to comment.