From d07b029f0567212b391759d9c43285157bc58458 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 8 Dec 2022 00:29:13 -0500 Subject: [PATCH 1/6] [mono] Add export_symbols_outfile parameter [mono] Export EntryPoint of methods decorated with UnmanagedCallersOnlyAttribute to specified export_symbols_outfile --- src/mono/mono/mini/aot-compiler.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 75249bea3ad1c6..ab0ff07e9dc015 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -187,6 +187,7 @@ typedef struct MonoAotOptions { char *outfile; char *llvm_outfile; char *data_outfile; + char *export_symbols_outfile; GList *profile_files; GList *mibc_profile_files; gboolean save_temps; @@ -406,6 +407,7 @@ typedef struct MonoAotCompile { FILE *logfile; FILE *instances_logfile; FILE *data_outfile; + FILE *export_symbols_outfile; int datafile_offset; int gc_name_offset; // In this mode, we are emitting dedupable methods that we encounter @@ -5103,6 +5105,12 @@ add_wrappers (MonoAotCompile *acfg) } } + if (acfg->aot_opts.export_symbols_outfile) { + acfg->export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "a"); + if (!acfg->export_symbols_outfile) + fprintf (stderr, "Unable to open file '%s': %s\n", acfg->aot_opts.export_symbols_outfile, strerror (errno)); + } + /* native-to-managed wrappers */ rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]); for (int i = 0; i < rows; ++i) { @@ -5252,8 +5260,12 @@ MONO_RESTORE_WARNING mono_error_assert_ok (error); add_method (acfg, wrapper); - if (export_name) + if (export_name) { g_hash_table_insert (acfg->export_names, wrapper, export_name); + + if (acfg->export_symbols_outfile) + fprintf (acfg->export_symbols_outfile, "%s\n", export_name); + } } g_free (cattr); @@ -5265,6 +5277,11 @@ MONO_RESTORE_WARNING } } + if (acfg->aot_opts.export_symbols_outfile) + g_free (acfg->aot_opts.export_symbols_outfile); + if (acfg->export_symbols_outfile) + fclose (acfg->export_symbols_outfile); + /* StructureToPtr/PtrToStructure wrappers */ rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPEDEF]); for (int i = 0; i < rows; ++i) { @@ -8445,6 +8462,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->outfile = g_strdup (arg + strlen ("outfile=")); } else if (str_begins_with (arg, "llvm-outfile=")) { opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile=")); + } else if (str_begins_with (arg, "export-symbols-outfile=")) { + opts->export_symbols_outfile = g_strdup (arg + strlen ("export-symbols-outfile=")); } else if (str_begins_with (arg, "temp-path=")) { opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path="))); } else if (str_begins_with (arg, "save-temps")) { From 2e322e7749cdc522e116c42bbc02ba1f9a74cc0c Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 8 Dec 2022 11:58:21 -0500 Subject: [PATCH 2/6] [mono] Create export file and export symbols iff there are specified EntryPoints --- src/mono/mono/mini/aot-compiler.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ab0ff07e9dc015..ef787fc635b035 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5105,12 +5105,7 @@ add_wrappers (MonoAotCompile *acfg) } } - if (acfg->aot_opts.export_symbols_outfile) { - acfg->export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "a"); - if (!acfg->export_symbols_outfile) - fprintf (stderr, "Unable to open file '%s': %s\n", acfg->aot_opts.export_symbols_outfile, strerror (errno)); - } - + GString *export_symbols = g_string_new (""); /* native-to-managed wrappers */ rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]); for (int i = 0; i < rows; ++i) { @@ -5262,9 +5257,7 @@ MONO_RESTORE_WARNING add_method (acfg, wrapper); if (export_name) { g_hash_table_insert (acfg->export_names, wrapper, export_name); - - if (acfg->export_symbols_outfile) - fprintf (acfg->export_symbols_outfile, "%s\n", export_name); + g_string_append_printf (export_symbols, "_%s\n", export_name); } } @@ -5277,10 +5270,19 @@ MONO_RESTORE_WARNING } } - if (acfg->aot_opts.export_symbols_outfile) + if (acfg->aot_opts.export_symbols_outfile && export_symbols->len) { + char *export_symbols_out = g_string_free (export_symbols, FALSE); + acfg->export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "w"); g_free (acfg->aot_opts.export_symbols_outfile); - if (acfg->export_symbols_outfile) + if (!acfg->export_symbols_outfile) { + fprintf (stderr, "Unable to open specified export_symbols_outfile '%s' to append symbols '%s': %s\n", acfg->aot_opts.export_symbols_outfile, export_symbols_out, strerror (errno)); + g_free (export_symbols_out); + exit (1); + } + fprintf (acfg->export_symbols_outfile, "%s", export_symbols_out); + g_free (export_symbols_out); fclose (acfg->export_symbols_outfile); + } /* StructureToPtr/PtrToStructure wrappers */ rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPEDEF]); From 4142a37400e557eefc96b68a946520aa09f9ce6a Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 8 Dec 2022 00:42:33 -0500 Subject: [PATCH 3/6] [task] Bootstrap export-symbols-outfile mono aot compiler option to MonoAOTCompiler Task --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 113ed9addafc12..c3c8a609069abf 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -163,6 +163,11 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// public string LibraryFilePrefix { get; set; } = ""; + /// + /// Enables exporting symbols of methods decorated with UnmanagedCallersOnly Attribute containing a specified EntryPoint + /// + public bool EnableUnmanagedCallersOnlyMethodsExport { get; set; } + /// /// Path to the directory where LLVM binaries (opt and llc) are found. /// It's required if UseLLVM is set @@ -729,6 +734,20 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st } } + if ((parsedAotMode == MonoAotMode.Full || + parsedAotMode == MonoAotMode.FullInterp || + parsedAotMode == MonoAotMode.LLVMOnly || + parsedAotMode == MonoAotMode.LLVMOnlyInterp) && + EnableUnmanagedCallersOnlyMethodsExport) + { + string exportSymbolsFile = Path.Combine(OutputDir, Path.ChangeExtension(assemblyFilename, ".exportsymbols")); + ProxyFile proxyFile = _cache.NewFile(exportSymbolsFile); + proxyFiles.Add(proxyFile); + + aotArgs.Add($"export-symbols-outfile={proxyFile.TempFile}"); + aotAssembly.SetMetadata("ExportSymbolsFile", proxyFile.TargetFile); + } + // pass msym-dir if specified if (MsymPath != null) { From 18dffe11a12cf687dadee7424fa9f936e234a868 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 8 Dec 2022 18:27:14 -0500 Subject: [PATCH 4/6] Format symbols based on platform --- src/mono/mono/mini/aot-compiler.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ef787fc635b035..4a57624598af57 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5257,7 +5257,11 @@ MONO_RESTORE_WARNING add_method (acfg, wrapper); if (export_name) { g_hash_table_insert (acfg->export_names, wrapper, export_name); +#ifdef TARGET_APPLE_MOBILE g_string_append_printf (export_symbols, "_%s\n", export_name); +#else + g_string_append_printf (export_symbols, "%s\n", export_name); +#endif } } From facb112d5b470c55793259c34e00b053658b6ddf Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 9 Dec 2022 12:43:01 -0500 Subject: [PATCH 5/6] Address feedback --- src/mono/mono/mini/aot-compiler.c | 18 ++++++------------ src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 6 +----- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 4a57624598af57..b8682fa5798c41 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -407,7 +407,6 @@ typedef struct MonoAotCompile { FILE *logfile; FILE *instances_logfile; FILE *data_outfile; - FILE *export_symbols_outfile; int datafile_offset; int gc_name_offset; // In this mode, we are emitting dedupable methods that we encounter @@ -5257,11 +5256,7 @@ MONO_RESTORE_WARNING add_method (acfg, wrapper); if (export_name) { g_hash_table_insert (acfg->export_names, wrapper, export_name); -#ifdef TARGET_APPLE_MOBILE - g_string_append_printf (export_symbols, "_%s\n", export_name); -#else - g_string_append_printf (export_symbols, "%s\n", export_name); -#endif + g_string_append_printf (export_symbols, "%s%s\n", acfg->user_symbol_prefix, export_name); } } @@ -5274,18 +5269,17 @@ MONO_RESTORE_WARNING } } - if (acfg->aot_opts.export_symbols_outfile && export_symbols->len) { + if (acfg->aot_opts.export_symbols_outfile) { char *export_symbols_out = g_string_free (export_symbols, FALSE); - acfg->export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "w"); - g_free (acfg->aot_opts.export_symbols_outfile); - if (!acfg->export_symbols_outfile) { + FILE* export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "w"); + if (!export_symbols_outfile) { fprintf (stderr, "Unable to open specified export_symbols_outfile '%s' to append symbols '%s': %s\n", acfg->aot_opts.export_symbols_outfile, export_symbols_out, strerror (errno)); g_free (export_symbols_out); exit (1); } - fprintf (acfg->export_symbols_outfile, "%s", export_symbols_out); + fprintf (export_symbols_outfile, "%s", export_symbols_out); g_free (export_symbols_out); - fclose (acfg->export_symbols_outfile); + fclose (export_symbols_outfile); } /* StructureToPtr/PtrToStructure wrappers */ diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index c3c8a609069abf..1a62f394f4bd93 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -734,11 +734,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st } } - if ((parsedAotMode == MonoAotMode.Full || - parsedAotMode == MonoAotMode.FullInterp || - parsedAotMode == MonoAotMode.LLVMOnly || - parsedAotMode == MonoAotMode.LLVMOnlyInterp) && - EnableUnmanagedCallersOnlyMethodsExport) + if (EnableUnmanagedCallersOnlyMethodsExport) { string exportSymbolsFile = Path.Combine(OutputDir, Path.ChangeExtension(assemblyFilename, ".exportsymbols")); ProxyFile proxyFile = _cache.NewFile(exportSymbolsFile); From b92b62d32dd65688fe677a400de72726adf18e36 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 9 Dec 2022 13:10:43 -0500 Subject: [PATCH 6/6] Check for exportsymbols when EnableUnmanagedCallersOnlyMethodsExport is true --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 1a62f394f4bd93..5b3e6b8ad62af4 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -483,6 +483,7 @@ all assigned to that one partition. } } + CheckExportSymbolsFile(_assembliesToCompile); CompiledAssemblies = ConvertAssembliesDictToOrderedList(compiledAssemblies, _assembliesToCompile).ToArray(); return !Log.HasLoggedErrors; } @@ -1055,6 +1056,21 @@ private bool TryGetAssemblyName(string asmPath, [NotNullWhen(true)] out string? } } + private void CheckExportSymbolsFile(IList assemblies) + { + if (!EnableUnmanagedCallersOnlyMethodsExport) + return; + + foreach (var assemblyItem in assemblies) + { + string assembly = assemblyItem.GetMetadata("FullPath"); + string assemblyFilename = Path.GetFileName(assembly); + string exportSymbolsFile = Path.Combine(OutputDir, Path.ChangeExtension(assemblyFilename, ".exportsymbols")); + if (!File.Exists(exportSymbolsFile)) + Log.LogWarning($"EnableUnmanagedCallersOnlyMethodsExport is true, but no .exportsymbols file generated for assembly '{assemblyFilename}'. Check that the AOT compilation mode is full."); + } + } + private static IList ConvertAssembliesDictToOrderedList(ConcurrentDictionary dict, IList originalAssemblies) { List outItems = new(originalAssemblies.Count);