Fix Diagnostics.Tracing ILLinkTrim entries (#38125)
authorEric Erhardt <eric.erhardt@microsoft.com>
Fri, 19 Jun 2020 14:52:36 +0000 (09:52 -0500)
committerGitHub <noreply@github.com>
Fri, 19 Jun 2020 14:52:36 +0000 (09:52 -0500)
* Fix Diagnostics.Tracing ILLinkTrim entries

- PropertyValue/ReferenceTypeHelper's pattern is recognized by the ILLinker. Protected it with a new trimming test.
- RuntimeEventSource doesn't need to be rooted. This class is used by IL and doesn't get trimmed.
- EventPipe* and NativeRuntimeEventSource only need to be rooted in CoreCLR, since they aren't used in Mono. So they are moved to just CoreCLR's ILLinkTrim file.

Contributes to #35199

src/coreclr/src/System.Private.CoreLib/ILLinkTrim.xml
src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs [new file with mode: 0644]
src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/System.Diagnostics.Tracing.TrimmingTests.proj [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.Shared.xml

index e5a4eeb..f24632d 100644 (file)
@@ -5,5 +5,9 @@
       <method name="_RegisterFrozenSegment" />
       <method name="_UnregisterFrozenSegment" />
     </type>
+    <!-- Accessed via private reflection by an external tracing controller. -->
+    <type fullname="System.Diagnostics.Tracing.EventPipe*" />
+    <!-- The private Event methods are accessed by private reflection in the base EventSource class. -->
+    <type fullname="System.Diagnostics.Tracing.NativeRuntimeEventSource" />
   </assembly>
 </linker>
diff --git a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs
new file mode 100644 (file)
index 0000000..cf3d949
--- /dev/null
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Tracing;
+
+/// <summary>
+/// Tests that using EventSource with a reference type EventData works on a
+/// trimmed application.
+/// See System.Diagnostics.Tracing.PropertyValue.GetReferenceTypePropertyGetter.
+/// </summary>
+internal class Program
+{
+    [EventData]
+    private class TestData
+    {
+        public int TestInt { get; set; }
+        public TestSubData SubData { get; set; }
+    }
+
+    [EventData]
+    private class TestSubData
+    {
+        public int SubInt { get; set; }
+    }
+
+    [EventSource(Name = EventSourceName)]
+    private class TestEventSource : EventSource
+    {
+        public const string EventSourceName = "MyTest";
+        public static TestEventSource Log = new TestEventSource();
+
+        public TestEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { }
+
+        [Event(1)]
+        public void LogData(TestData data)
+        {
+            Write("LogData", data);
+        }
+    }
+
+    private class TestEventListener : EventListener
+    {
+        public ReadOnlyCollection<object> LogDataPayload { get; set; }
+
+        protected override void OnEventSourceCreated(EventSource eventSource)
+        {
+            if (eventSource.Name == TestEventSource.EventSourceName)
+            {
+                EnableEvents(eventSource, EventLevel.Verbose);
+            }
+
+            base.OnEventSourceCreated(eventSource);
+        }
+
+        protected override void OnEventWritten(EventWrittenEventArgs eventData)
+        {
+            if (eventData.EventName == "LogData")
+            {
+                LogDataPayload = eventData.Payload;
+            }
+
+            base.OnEventWritten(eventData);
+        }
+    }
+
+    public static int Main()
+    {
+        using (var listener = new TestEventListener())
+        {
+            var testData = new TestData()
+            {
+                TestInt = 5,
+                SubData = new TestSubData()
+                {
+                    SubInt = 6
+                }
+            };
+            TestEventSource.Log.LogData(testData);
+
+            if (listener.LogDataPayload?.Count == 2 &&
+                (int)listener.LogDataPayload[0] == testData.TestInt &&
+                (int)((IDictionary<string, object>)listener.LogDataPayload[1])["SubInt"] == testData.SubData.SubInt)
+            {
+                return 100;
+            }
+
+            return -1;
+        }
+    }
+}
diff --git a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/System.Diagnostics.Tracing.TrimmingTests.proj b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/System.Diagnostics.Tracing.TrimmingTests.proj
new file mode 100644 (file)
index 0000000..da4a46f
--- /dev/null
@@ -0,0 +1,5 @@
+<Project DefaultTargets="Build">
+  <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
+
+  <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
+</Project>
index 87750a9..6a3fc8f 100644 (file)
       <!-- Methods is used by VS Tasks Window. -->
       <method name="GetActiveTaskFromId" />
     </type>
-    <!-- Accessed via private reflection by tracing controller. -->
-    <type fullname="System.Diagnostics.Tracing.EventPipe*" />
-    <!-- Accessed via private reflection and by native code. -->
-    <type fullname="System.Diagnostics.Tracing.RuntimeEventSource" />
-    <type fullname="System.Diagnostics.Tracing.NativeRuntimeEventSource" />
-    <type fullname="System.Diagnostics.Tracing.PropertyValue/ReferenceTypeHelper`1">
-      <!-- Instantiated via reflection -->
-      <method name=".ctor" />
-    </type>
     <!-- Accessed via native code. -->
     <type fullname="System.Runtime.InteropServices.ComTypes.IEnumerable" />
     <type fullname="System.Runtime.InteropServices.ComTypes.IEnumerator" />