Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ Copyright (c) .NET Foundation. All rights reserved.

<PropertyGroup>
<ILLinkTreatWarningsAsErrors Condition=" '$(ILLinkTreatWarningsAsErrors)' == '' ">$(TreatWarningsAsErrors)</ILLinkTreatWarningsAsErrors>
<_ExtraTrimmerArgs>--skip-unresolved true $(_ExtraTrimmerArgs)</_ExtraTrimmerArgs>
<TrimmerSingleWarn Condition=" '$(TrimmerSingleWarn)' == '' ">true</TrimmerSingleWarn>
</PropertyGroup>

Expand Down
12 changes: 0 additions & 12 deletions src/tools/illink/src/linker/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1387,12 +1387,6 @@
<Left>ref/net8.0/illink.dll</Left>
<Right>lib/net8.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.get_IgnoreUnresolved</Target>
<Left>ref/net8.0/illink.dll</Left>
<Right>lib/net8.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.get_KeepUsedAttributeTypesOnly</Target>
Expand Down Expand Up @@ -1831,12 +1825,6 @@
<Left>ref/net8.0/illink.dll</Left>
<Right>lib/net8.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.set_IgnoreUnresolved(System.Boolean)</Target>
<Left>ref/net8.0/illink.dll</Left>
<Right>lib/net8.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.set_KeepUsedAttributeTypesOnly(System.Boolean)</Target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ static void InitializeExportedType (ExportedType exportedType, LinkContext conte
if (!context.Annotations.TryGetPreservedMembers (exportedType, out TypePreserveMembers members))
return;

TypeDefinition? type = context.TryResolve (exportedType);
TypeDefinition? type = context.TryResolve (exportedType, assembly.MainModule);
if (type == null) {
if (!context.IgnoreUnresolved)
context.LogError (null, DiagnosticId.ExportedTypeCannotBeResolved, exportedType.Name);

context.LogError (null, DiagnosticId.ExportedTypeCannotBeResolved, exportedType.Name);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/tools/illink/src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ protected override void ProcessTypeReference (TypeReference type)
markingHelpers.MarkForwardedScope (type, new MessageOrigin (assembly));
}

protected override void ProcessExportedType (ExportedType exportedType)
protected override void ProcessExportedType (ExportedType exportedType, ModuleDefinition module)
{
markingHelpers.MarkExportedType (exportedType, assembly.MainModule, new DependencyInfo (DependencyKind.ExportedType, assembly), new MessageOrigin (assembly));
markingHelpers.MarkForwardedScope (CreateTypeReferenceForExportedTypeTarget (exportedType), new MessageOrigin (assembly));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ protected virtual void ProcessTypes (AssemblyDefinition assembly, XPathNavigator
}
}

protected virtual TypeDefinition? ProcessExportedType (ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => _context.TryResolve (exported);
protected virtual TypeDefinition? ProcessExportedType (ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => _context.TryResolve (exported, assembly.MainModule);

void MatchType (TypeDefinition type, Regex regex, XPathNavigator nav)
{
Expand Down
12 changes: 5 additions & 7 deletions src/tools/illink/src/linker/Linker.Steps/SweepStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,8 @@ protected override void ProcessTypeReference (TypeReference type)
#pragma warning restore RS0030
if (td == null) {
//
// This can happen when not all assembly refences were provided and we
// run in `--skip-unresolved` mode. We cannot fully sweep and keep the
// original assembly reference
// This can happen when not all assembly refences were provided.
// We cannot fully sweep and keep the original assembly reference.
//
var anr = (AssemblyNameReference) type.Scope;
type.Scope = importer.ImportReference (anr);
Expand All @@ -629,14 +628,13 @@ protected override void ProcessTypeReference (TypeReference type)
ChangedAnyScopes = true;
}

protected override void ProcessExportedType (ExportedType exportedType)
protected override void ProcessExportedType (ExportedType exportedType, ModuleDefinition module)
{
#pragma warning disable RS0030 // Cecil's Resolve is banned -- it's necessary when the metadata graph is unstable
TypeDefinition? td = exportedType.Resolve ();
TypeDefinition? td = exportedType.TryResolve (module);
#pragma warning restore RS0030
if (td == null) {
// Forwarded type cannot be resolved but it was marked
// ILLink is running in --skip-unresolved true mode
// Forwarded type cannot be resolved but it was marked.
var anr = (AssemblyNameReference) exportedType.Scope;
exportedType.Scope = importer.ImportReference (anr);
return;
Expand Down
5 changes: 1 addition & 4 deletions src/tools/illink/src/linker/Linker/AssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,7 @@ void ReportUnresolvedAssembly (AssemblyNameReference reference)
if (!_reportedUnresolvedAssemblies.Add (reference.Name))
return;

if (_context.IgnoreUnresolved)
_context.LogMessage ($"Ignoring unresolved assembly '{reference.Name}' reference.");
else
_context.LogError (null, DiagnosticId.CouldNotFindAssemblyReference, reference.Name);
_context.LogError (null, DiagnosticId.CouldNotFindAssemblyReference, reference.Name);
}

public void AddSearchDirectory (string directory)
Expand Down
7 changes: 0 additions & 7 deletions src/tools/illink/src/linker/Linker/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,6 @@ protected int SetupContext (ILogger? customLogger = null)
Usage ();
return 1;

case "--skip-unresolved":
if (!GetBoolParam (token, l => context.IgnoreUnresolved = l))
return -1;

continue;

case "--verbose":
context.LogMessages = true;
continue;
Expand Down Expand Up @@ -1336,7 +1330,6 @@ static void Usage ()
Console.WriteLine (" --custom-data KEY=VALUE Populates context data set with user specified key-value pair");
Console.WriteLine (" --deterministic Produce a deterministic output for modified assemblies");
Console.WriteLine (" --ignore-descriptors Skips reading embedded descriptors (short -z). Defaults to false");
Console.WriteLine (" --skip-unresolved Ignore unresolved types, methods, and assemblies. Defaults to false");
Console.WriteLine (" --output-pinvokes PATH Output a JSON file with all modules and entry points of the P/Invokes found");
Console.WriteLine (" --verbose Log messages indicating progress and warnings");
Console.WriteLine (" --nowarn WARN Disable specific warning messages");
Expand Down
123 changes: 123 additions & 0 deletions src/tools/illink/src/linker/Linker/ExportedTypeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using Mono.Cecil;

namespace Mono.Linker;

public static class ExportedTypeExtensions {

// Logic copied from cecil, to allow resolving exported types without errors on assembly resolution failures.
// This replaces the call to AssemblyResolver.Resolve (which logs errors on resolution failure) with a call to
// an overload that doesn't log errors.
// The ModuleDefinition containing the ExportedType must be passed in because it is not accessible
// on ExportedType.
public static TypeDefinition? TryResolve (this ExportedType exportedType, ModuleDefinition module) {
// Note: the cast from IMetadataResolver to Metadataresolver should always succeed because cecil only
// creates a MetadataResolver.
return ((MetadataResolver) module.MetadataResolver).TryResolve (exportedType.CreateReference (module));
}

private static TypeReference CreateReference (this ExportedType exportedType, ModuleDefinition module) {
return new TypeReference (exportedType.Namespace, exportedType.Name, module, exportedType.Scope) {
DeclaringType = exportedType.DeclaringType?.CreateReference (module),
};
}

private static TypeDefinition? TryResolve (this MetadataResolver metadataResolver, TypeReference type) {
type = type.GetElementType ();

var scope = type.Scope;

if (scope == null)
return null;

switch (scope.MetadataScopeType) {
case MetadataScopeType.AssemblyNameReference:
// Note: the cast to AssemblyResolver assumes that the IAssemblyResolver we get back from cecil
// is the same one that we originally passed in using ReaderParameters.
var assembly = ((AssemblyResolver) metadataResolver.AssemblyResolver).Resolve ((AssemblyNameReference) scope, probing: true);
if (assembly == null)
return null;

return metadataResolver.GetType (assembly.MainModule, type);
case MetadataScopeType.ModuleDefinition:
return metadataResolver.GetType ((ModuleDefinition) scope, type);
case MetadataScopeType.ModuleReference:
if (type.Module.Assembly == null)
return null;

var modules = type.Module.Assembly.Modules;
var module_ref = (ModuleReference) scope;
for (int i = 0; i < modules.Count; i++) {
var netmodule = modules [i];
if (netmodule.Name == module_ref.Name)
return metadataResolver.GetType (netmodule, type);
}
break;
}

throw new NotSupportedException ();
}

private static TypeDefinition? GetType (this MetadataResolver metadataResolver, ModuleDefinition module, TypeReference reference) {
var type = metadataResolver.GetTypeDefinition (module, reference);
if (type != null)
return type;

if (!module.HasExportedTypes)
return null;

var exported_types = module.ExportedTypes;

for (int i = 0; i < exported_types.Count; i++) {
var exported_type = exported_types [i];
if (exported_type.Name != reference.Name)
continue;

if (exported_type.Namespace != reference.Namespace)
continue;

return exported_type.TryResolve (module);
}

return null;
}

private static TypeDefinition? GetTypeDefinition (this MetadataResolver metadtaaResolver, ModuleDefinition module, TypeReference type)
{
if (!type.IsNested)
return module.GetType (type.Namespace, type.Name);

var declaring_type = metadtaaResolver.TryResolve (type.DeclaringType);
if (declaring_type == null)
return null;

return declaring_type.GetNestedType (type.TypeFullName ());
}

private static string TypeFullName (this TypeReference self)
{
return string.IsNullOrEmpty (self.Namespace)
? self.Name
: self.Namespace + '.' + self.Name;
}

private static TypeDefinition? GetNestedType (this TypeDefinition self, string fullname)
{
if (!self.HasNestedTypes)
return null;

var nested_types = self.NestedTypes;

for (int i = 0; i < nested_types.Count; i++) {
var nested_type = nested_types [i];

if (nested_type.TypeFullName () == fullname)
return nested_type;
}

return null;
}
}
24 changes: 14 additions & 10 deletions src/tools/illink/src/linker/Linker/LinkContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ public Pipeline Pipeline {

public readonly bool KeepMembersForDebugger = true;

public bool IgnoreUnresolved { get; set; }

public bool EnableReducedTracing { get; set; }

public bool KeepUsedAttributeTypesOnly { get; set; }
Expand Down Expand Up @@ -291,6 +289,12 @@ public bool HasFeatureValue (string feature, bool value)
return _resolver.Resolve (reference);
}

public AssemblyDefinition? TryResolve (IMetadataScope scope)
{
AssemblyNameReference reference = GetReference (scope);
return _resolver.Resolve (reference, probing: true);
}

public AssemblyDefinition? Resolve (AssemblyNameReference name)
{
return _resolver.Resolve (name);
Expand Down Expand Up @@ -344,7 +348,7 @@ public virtual ICollection<AssemblyDefinition> ResolveReferences (AssemblyDefini
return references;

foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) {
AssemblyDefinition? definition = Resolve (reference);
AssemblyDefinition? definition = TryResolve (reference);
if (definition != null)
references.Add (definition);
}
Expand Down Expand Up @@ -774,7 +778,7 @@ public int GetTargetRuntimeVersion ()
#pragma warning disable RS0030 // Cecil's resolve is banned -- this provides the wrapper
md = methodReference.Resolve ();
#pragma warning restore RS0030
if (md == null && !IgnoreUnresolved)
if (md == null)
ReportUnresolved (methodReference);

methodresolveCache.Add (methodReference, md);
Expand Down Expand Up @@ -817,7 +821,7 @@ public int GetTargetRuntimeVersion ()
return fd;

fd = fieldReference.Resolve ();
if (fd == null && !IgnoreUnresolved)
if (fd == null)
ReportUnresolved (fieldReference);

fieldresolveCache.Add (fieldReference, fd);
Expand Down Expand Up @@ -866,7 +870,7 @@ public int GetTargetRuntimeVersion ()
#pragma warning disable RS0030
td = typeReference.Resolve ();
#pragma warning restore RS0030
if (td == null && !IgnoreUnresolved)
if (td == null)
ReportUnresolved (typeReference);

typeresolveCache.Add (typeReference, td);
Expand Down Expand Up @@ -909,9 +913,9 @@ public int GetTargetRuntimeVersion ()
/// <summary>
/// Tries to resolve the ExportedType to a TypeDefinition and logs a warning if it can't
/// </summary>
public TypeDefinition? Resolve (ExportedType et)
public TypeDefinition? Resolve (ExportedType et, ModuleDefinition module)
{
if (TryResolve (et) is not TypeDefinition td) {
if (TryResolve (et, module) is not TypeDefinition td) {
ReportUnresolved (et);
return null;
}
Expand All @@ -921,13 +925,13 @@ public int GetTargetRuntimeVersion ()
/// <summary>
/// Tries to resolve the ExportedType to a TypeDefinition and returns null if it can't
/// </summary>
public TypeDefinition? TryResolve (ExportedType et)
public TypeDefinition? TryResolve (ExportedType et, ModuleDefinition module)
{
if (exportedTypeResolveCache.TryGetValue (et, out var td)) {
return td;
}
#pragma warning disable RS0030 // Cecil's Resolve is banned -- this method provides the wrapper
td = et.Resolve ();
td = et.TryResolve (module);
#pragma warning restore RS0030
exportedTypeResolveCache.Add (et, td);
return td;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/illink/src/linker/Linker/MarkingHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void MarkForwardedScope (TypeReference typeReference, in MessageOrigin or
return;

if (typeReference.Scope is AssemblyNameReference) {
var assembly = _context.Resolve (typeReference.Scope);
var assembly = _context.TryResolve (typeReference.Scope);
if (assembly != null &&
_context.TryResolve (typeReference) is TypeDefinition typeDefinition &&
assembly.MainModule.GetMatchingExportedType (typeDefinition, _context, out var exportedType))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static bool GetMatchingExportedType (this ModuleDefinition module, TypeDe
return false;

foreach (var et in module.ExportedTypes) {
if (context.TryResolve (et) == typeDefinition) {
if (context.TryResolve (et, module) == typeDefinition) {
exportedType = et;
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions src/tools/illink/src/linker/Linker/TypeReferenceWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public virtual void Process ()
}

if (mmodule.HasExportedTypes)
WalkTypeScope (mmodule.ExportedTypes);
WalkTypeScope (mmodule.ExportedTypes, mmodule);

ProcessExtra ();
}
Expand Down Expand Up @@ -152,10 +152,10 @@ void WalkTypeScope (Collection<ParameterDefinition> parameters)
}
}

void WalkTypeScope (Collection<ExportedType> forwarders)
void WalkTypeScope (Collection<ExportedType> forwarders, ModuleDefinition module)
{
foreach (var f in forwarders)
ProcessExportedType (f);
ProcessExportedType (f, module);
}

void WalkTypeScope (MethodBody body)
Expand Down Expand Up @@ -373,7 +373,7 @@ void WalkScopeOfTypeReference (TypeReference type)

protected abstract void ProcessTypeReference (TypeReference type);

protected abstract void ProcessExportedType (ExportedType exportedType);
protected abstract void ProcessExportedType (ExportedType exportedType, ModuleDefinition module);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace Mono.Linker.Tests.Cases.Attributes
[SetupLinkerTrimMode ("link")]
// System.dll referenced by a dynamically (for example in TypeConverterAttribute on IComponent)
// has unresolved references.
[SetupLinkerArgument ("--skip-unresolved", "true")]
[KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))]
[KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyCompanyAttribute))]
#if !NETCOREAPP
Expand Down
Loading