diff --git a/eng/testing/linker/SupportFiles/Directory.Build.targets b/eng/testing/linker/SupportFiles/Directory.Build.targets
index 90ce573551e90d..f1603cde43ad9d 100644
--- a/eng/testing/linker/SupportFiles/Directory.Build.targets
+++ b/eng/testing/linker/SupportFiles/Directory.Build.targets
@@ -19,6 +19,17 @@
+
+
+
+
+ <_ManagedAssembliesToLink>
+ link
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs
index 500a946951bcff..1f99516869be62 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace System.Diagnostics
{
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)]
@@ -8,7 +10,8 @@ public sealed class DebuggerTypeProxyAttribute : Attribute
{
private Type? _target;
- public DebuggerTypeProxyAttribute(Type type)
+ public DebuggerTypeProxyAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type)
{
if (type == null)
{
@@ -18,11 +21,15 @@ public DebuggerTypeProxyAttribute(Type type)
ProxyTypeName = type.AssemblyQualifiedName!;
}
- public DebuggerTypeProxyAttribute(string typeName)
+ public DebuggerTypeProxyAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName)
{
ProxyTypeName = typeName;
}
+ // The Proxy is only invoked by the debugger, so it needs to have its
+ // members preserved
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public string ProxyTypeName { get; }
public Type? Target
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index ee91e1dd2f824e..548f48bede5543 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -5715,8 +5715,9 @@ public DebuggerStepThroughAttribute() { }
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=true)]
public sealed partial class DebuggerTypeProxyAttribute : System.Attribute
{
- public DebuggerTypeProxyAttribute(string typeName) { }
- public DebuggerTypeProxyAttribute(System.Type type) { }
+ public DebuggerTypeProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string typeName) { }
+ public DebuggerTypeProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type) { }
+ [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)]
public string ProxyTypeName { get { throw null; } }
public System.Type? Target { get { throw null; } set { } }
public string? TargetTypeName { get { throw null; } set { } }
diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs b/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs
new file mode 100644
index 00000000000000..b80f4a1d61b00b
--- /dev/null
+++ b/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Diagnostics;
+
+///
+/// Tests that types used by DebuggerTypeProxyAttribute are not trimmed out
+/// when Debugger.IsSupported is true (the default).
+///
+class Program
+{
+ static int Main(string[] args)
+ {
+ MyClass myClass = new MyClass() { Name = "trimmed" };
+ MyClassWithProxyString myClassWithString = new MyClassWithProxyString() { Name = "trimmed" };
+
+ Type[] allTypes = typeof(MyClass).Assembly.GetTypes();
+ bool foundDebuggerProxy = false;
+ bool foundStringDebuggerProxy = false;
+ for (int i = 0; i < allTypes.Length; i++)
+ {
+ Type currentType = allTypes[i];
+ if (currentType.FullName == "Program+MyClass+DebuggerProxy" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundDebuggerProxy = true;
+ }
+ else if (currentType.FullName == "Program+MyClassWithProxyStringProxy" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundStringDebuggerProxy = true;
+ }
+ }
+
+ return foundDebuggerProxy && foundStringDebuggerProxy ? 100 : -1;
+ }
+
+ [DebuggerTypeProxy(typeof(DebuggerProxy))]
+ public class MyClass
+ {
+ public string Name { get; set; }
+
+ private class DebuggerProxy
+ {
+ private MyClass _instance;
+
+ public DebuggerProxy(MyClass instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " Proxy";
+ }
+ }
+
+ [DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")]
+ public class MyClassWithProxyString
+ {
+ public string Name { get; set; }
+ }
+
+ internal class MyClassWithProxyStringProxy
+ {
+ private MyClassWithProxyString _instance;
+
+ public MyClassWithProxyStringProxy(MyClassWithProxyString instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " StringProxy";
+ }
+}
diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs b/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs
index c30fb88e0b836b..aaf82add5a0519 100644
--- a/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs
+++ b/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs
@@ -10,6 +10,10 @@ class Program
{
static int Main(string[] args)
{
+ // workaround TypeConverterAttribute not being annotated correctly
+ // https://github.com/dotnet/runtime/issues/39125
+ var _ = new MyStringConverter();
+
TypeDescriptor.AddAttributes(typeof(string), new TypeConverterAttribute(typeof(MyStringConverter)));
var attribute = new DefaultValueAttribute(typeof(string), "Hello, world!");
diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj b/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj
index cfd1a4d2a7b81b..ce96e07448a3cc 100644
--- a/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj
+++ b/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj
@@ -6,6 +6,8 @@
osx-x64;linux-x64
+
+