Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[dotnet] Prevent linking out code referenced by P/Invoke #10182

Merged
merged 6 commits into from
Dec 3, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@
<ReadItemsFromFile File="$(_LinkerItemsDirectory)/_RegistrarFile.items" Condition="Exists('$(_LinkerItemsDirectory)/_RegistrarFile.items')">
<Output TaskParameter="Items" ItemName="_RegistrarFile" />
</ReadItemsFromFile>
<!-- Load _RegistrarFile -->
<ReadItemsFromFile File="$(_LinkerItemsDirectory)/_ReferencesFile.items" Condition="Exists('$(_LinkerItemsDirectory)/_ReferencesFile.items')">
<Output TaskParameter="Items" ItemName="_ReferencesFile" />
</ReadItemsFromFile>

<ItemGroup>
<_AssembliesToAOT Include="@(ResolvedFileToPublish)" Condition="'%(Extension)' == '.dll' Or '%(Extension)' == '.exe' " />
Expand Down Expand Up @@ -467,6 +471,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
1 change: 1 addition & 0 deletions tools/dotnet-linker/SetupStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ protected override void TryProcess ()
Steps.Add (new ExtractBindingLibrariesStep ());
Steps.Add (new RegistrarStep ());
Steps.Add (new GenerateMainStep ());
Steps.Add (new GenerateReferencesStep ());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear in PR but it seems to be after sweeping/cleaning.
Do check that enabling the linker result in less generated symbols (to keep around)

Steps.Add (new GatherFrameworksStep ());

Configuration.Write ();
Expand Down
74 changes: 74 additions & 0 deletions tools/dotnet-linker/Steps/GenerateReferencesStep.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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 {
private Symbols required_symbols = new Symbols ();

protected override string Name { get; } = "Generate References";
protected override int ErrorCode { get; } = 2320;

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

var items = new List<MSBuildItem> ();
var file = Path.Combine (Configuration.CacheDirectory, $"references.mm");
if (Configuration.Target.GenerateReferencingSource (file, required_symbols) != null) {
var item = new MSBuildItem { Include = file };
items.Add (item);
}
Configuration.WriteOutputForMSBuild ("_ReferencesFile", items);
}

protected override void TryProcessAssembly (AssemblyDefinition assembly)
{
base.TryProcessAssembly (assembly);

if (!assembly.MainModule.HasTypes)
return;

var hasSymbols = false;
if (assembly.MainModule.HasModuleReferences) {
hasSymbols = true;
} else if (assembly.MainModule.HasTypeReference ("Foundation.FieldAttribute")) {
hasSymbols = true;
}
if (!hasSymbols)
return;

foreach (var type in assembly.MainModule.Types)
ProcessType (type);
}

void ProcessType (TypeDefinition type)
{
if (type.HasNestedTypes) {
foreach (var nested in type.NestedTypes)
ProcessType (nested);
}

if (type.HasMethods) {
foreach (var method in type.Methods)
ProcessMethod (method);
}
}

void ProcessMethod (MethodDefinition method)
{
if (method.IsPInvokeImpl && method.HasPInvokeInfo && method.PInvokeInfo != null) {
var pinfo = method.PInvokeInfo;
if (pinfo.Module.Name == "__Internal") {
required_symbols.AddFunction (pinfo.EntryPoint).AddMember (method);
}
}
}
}
}