From 872698f69de04514d3a254c306f934b0ec4aa22f Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Fri, 4 Jun 2021 12:22:41 -0400 Subject: [PATCH] AOTCompilerTask: use assembly name to build the aot linking symbols (#53659) `System.Runtime.Loader.DefaultContext.Tests` fail with `wasm+aot` Fixes https://github.com/dotnet/runtime/issues/52383 From the issue: ``` [10:39:59] info: * Assertion at /__w/1/s/src/mono/mono/mini/aot-runtime.c:2330, condition `' not met [10:39:59] info: [10:39:59] info: ABORT: undefined [10:39:59] info: Stacktrace: [10:39:59] info: [10:39:59] info: Error [10:39:59] info: at Object.onAbort (runtime.js:217:13) [10:39:59] info: at abort (dotnet.js:1233:22) [10:39:59] info: at _abort (dotnet.js:5561:7) [10:39:59] info: at monoeg_assert_abort (:wasm-function[5943]:0xdadad) [10:39:59] info: at monoeg_log_default_handler (:wasm-function[5960]:0xdb0c8) [10:39:59] info: at monoeg_g_logstr (:wasm-function[5953]:0xdaf76) [10:39:59] info: at monoeg_g_logv_nofree (:wasm-function[5951]:0xdaf28) [10:39:59] info: at monoeg_assertion_message (:wasm-function[5956]:0xdaff2) [10:39:59] info: at mono_assertion_message (:wasm-function[5958]:0xdb035) [10:39:59] info: at mono_assertion_message_disabled (:wasm-function[5957]:0xdb008) [10:39:59] info: at mono_aot_register_module (:wasm-function[5045]:0xbb12a) [10:39:59] info: at register_aot_modules (:wasm-function[59156]:0x12f4753) ``` vargaz: This actually happens because the generated AOT linking symbol in driver-gen.c is not correct. Its generated from the filename, which is System.Runtime.Loader.Noop.Assembly_test.dll, but the assembly name is System.Runtime.Loader.Noop.Assembly. So linking the final app should fail, but emscripten doesn't notice the missing symbol because of https://github.com/emscripten-core/emscripten/issues/14106 . So this turns into a runtime assertion. - Also, enable the tests. --- src/libraries/tests.proj | 3 -- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 52 ++++++++++++++++--- .../AotCompilerTask/MonoAOTCompiler.csproj | 1 + 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 52e741621ab..d624fdc8407 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -261,9 +261,6 @@ - - - diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 3f194797a38..52d37fe900e 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -7,10 +7,12 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; +using System.Reflection.PortableExecutable; public class MonoAOTCompiler : Microsoft.Build.Utilities.Task { @@ -217,10 +219,8 @@ public override bool Execute() throw new ArgumentException($"'{nameof(AotModulesTableLanguage)}' must be one of: '{nameof(MonoAotModulesTableLanguage.C)}', '{nameof(MonoAotModulesTableLanguage.ObjC)}'. Received: '{AotModulesTableLanguage}'.", nameof(AotModulesTableLanguage)); } - if (!string.IsNullOrEmpty(AotModulesTablePath)) - { - GenerateAotModulesTable(Assemblies, Profilers); - } + if (!string.IsNullOrEmpty(AotModulesTablePath) && !GenerateAotModulesTable(Assemblies, Profilers)) + return false; string? monoPaths = null; if (AdditionalAssemblySearchPaths != null) @@ -431,13 +431,23 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) return true; } - private void GenerateAotModulesTable(ITaskItem[] assemblies, string[]? profilers) + private bool GenerateAotModulesTable(ITaskItem[] assemblies, string[]? profilers) { var symbols = new List(); foreach (var asm in assemblies) { - var name = Path.GetFileNameWithoutExtension(asm.ItemSpec).Replace ('.', '_').Replace ('-', '_'); - symbols.Add($"mono_aot_module_{name}_info"); + string asmPath = asm.ItemSpec; + if (!File.Exists(asmPath)) + { + Log.LogError($"Could not find assembly {asmPath}"); + return false; + } + + if (!TryGetAssemblyName(asmPath, out string? assemblyName)) + return false; + + string symbolName = assemblyName.Replace ('.', '_').Replace ('-', '_'); + symbols.Add($"mono_aot_module_{symbolName}_info"); } Directory.CreateDirectory(Path.GetDirectoryName(AotModulesTablePath!)!); @@ -504,6 +514,34 @@ private void GenerateAotModulesTable(ITaskItem[] assemblies, string[]? profilers } Log.LogMessage(MessageImportance.Low, $"Generated {AotModulesTablePath}"); } + + return true; + } + + private bool TryGetAssemblyName(string asmPath, [NotNullWhen(true)] out string? assemblyName) + { + assemblyName = null; + + try + { + using var fs = new FileStream(asmPath, FileMode.Open, FileAccess.Read); + using var peReader = new PEReader(fs); + MetadataReader mr = peReader.GetMetadataReader(); + assemblyName = mr.GetAssemblyDefinition().GetAssemblyName().Name; + + if (string.IsNullOrEmpty(assemblyName)) + { + Log.LogError($"Could not get assembly name for {asmPath}"); + return false; + } + + return true; + } + catch (Exception ex) + { + Log.LogError($"Failed to get assembly name for {asmPath}: {ex.Message}"); + return false; + } } } diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj index 1538b0669b9..79baa5b8b39 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj @@ -15,6 +15,7 @@ + -- GitLab