Skip to content

Commit 73b5ac0

Browse files
authored
[mono] Export unmanagedcallersonly method symbols (#79424)
* [mono] Add export_symbols_outfile parameter [mono] Export EntryPoint of methods decorated with UnmanagedCallersOnlyAttribute to specified export_symbols_outfile * [mono] Create export file and export symbols iff there are specified EntryPoints * [task] Bootstrap export-symbols-outfile mono aot compiler option to MonoAOTCompiler Task * Format symbols based on platform * Address feedback * Check for exportsymbols when EnableUnmanagedCallersOnlyMethodsExport is true
1 parent c9175cc commit 73b5ac0

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/mono/mono/mini/aot-compiler.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ typedef struct MonoAotOptions {
187187
char *outfile;
188188
char *llvm_outfile;
189189
char *data_outfile;
190+
char *export_symbols_outfile;
190191
GList *profile_files;
191192
GList *mibc_profile_files;
192193
gboolean save_temps;
@@ -5103,6 +5104,7 @@ add_wrappers (MonoAotCompile *acfg)
51035104
}
51045105
}
51055106

5107+
GString *export_symbols = g_string_new ("");
51065108
/* native-to-managed wrappers */
51075109
rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]);
51085110
for (int i = 0; i < rows; ++i) {
@@ -5252,8 +5254,10 @@ MONO_RESTORE_WARNING
52525254
mono_error_assert_ok (error);
52535255

52545256
add_method (acfg, wrapper);
5255-
if (export_name)
5257+
if (export_name) {
52565258
g_hash_table_insert (acfg->export_names, wrapper, export_name);
5259+
g_string_append_printf (export_symbols, "%s%s\n", acfg->user_symbol_prefix, export_name);
5260+
}
52575261
}
52585262

52595263
g_free (cattr);
@@ -5265,6 +5269,19 @@ MONO_RESTORE_WARNING
52655269
}
52665270
}
52675271

5272+
if (acfg->aot_opts.export_symbols_outfile) {
5273+
char *export_symbols_out = g_string_free (export_symbols, FALSE);
5274+
FILE* export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "w");
5275+
if (!export_symbols_outfile) {
5276+
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));
5277+
g_free (export_symbols_out);
5278+
exit (1);
5279+
}
5280+
fprintf (export_symbols_outfile, "%s", export_symbols_out);
5281+
g_free (export_symbols_out);
5282+
fclose (export_symbols_outfile);
5283+
}
5284+
52685285
/* StructureToPtr/PtrToStructure wrappers */
52695286
rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPEDEF]);
52705287
for (int i = 0; i < rows; ++i) {
@@ -8445,6 +8462,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
84458462
opts->outfile = g_strdup (arg + strlen ("outfile="));
84468463
} else if (str_begins_with (arg, "llvm-outfile=")) {
84478464
opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile="));
8465+
} else if (str_begins_with (arg, "export-symbols-outfile=")) {
8466+
opts->export_symbols_outfile = g_strdup (arg + strlen ("export-symbols-outfile="));
84488467
} else if (str_begins_with (arg, "temp-path=")) {
84498468
opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path=")));
84508469
} else if (str_begins_with (arg, "save-temps")) {

src/tasks/AotCompilerTask/MonoAOTCompiler.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task
163163
/// </summary>
164164
public string LibraryFilePrefix { get; set; } = "";
165165

166+
/// <summary>
167+
/// Enables exporting symbols of methods decorated with UnmanagedCallersOnly Attribute containing a specified EntryPoint
168+
/// </summary>
169+
public bool EnableUnmanagedCallersOnlyMethodsExport { get; set; }
170+
166171
/// <summary>
167172
/// Path to the directory where LLVM binaries (opt and llc) are found.
168173
/// It's required if UseLLVM is set
@@ -478,6 +483,7 @@ all assigned to that one partition.
478483
}
479484
}
480485

486+
CheckExportSymbolsFile(_assembliesToCompile);
481487
CompiledAssemblies = ConvertAssembliesDictToOrderedList(compiledAssemblies, _assembliesToCompile).ToArray();
482488
return !Log.HasLoggedErrors;
483489
}
@@ -729,6 +735,16 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st
729735
}
730736
}
731737

738+
if (EnableUnmanagedCallersOnlyMethodsExport)
739+
{
740+
string exportSymbolsFile = Path.Combine(OutputDir, Path.ChangeExtension(assemblyFilename, ".exportsymbols"));
741+
ProxyFile proxyFile = _cache.NewFile(exportSymbolsFile);
742+
proxyFiles.Add(proxyFile);
743+
744+
aotArgs.Add($"export-symbols-outfile={proxyFile.TempFile}");
745+
aotAssembly.SetMetadata("ExportSymbolsFile", proxyFile.TargetFile);
746+
}
747+
732748
// pass msym-dir if specified
733749
if (MsymPath != null)
734750
{
@@ -1040,6 +1056,21 @@ private bool TryGetAssemblyName(string asmPath, [NotNullWhen(true)] out string?
10401056
}
10411057
}
10421058

1059+
private void CheckExportSymbolsFile(IList<ITaskItem> assemblies)
1060+
{
1061+
if (!EnableUnmanagedCallersOnlyMethodsExport)
1062+
return;
1063+
1064+
foreach (var assemblyItem in assemblies)
1065+
{
1066+
string assembly = assemblyItem.GetMetadata("FullPath");
1067+
string assemblyFilename = Path.GetFileName(assembly);
1068+
string exportSymbolsFile = Path.Combine(OutputDir, Path.ChangeExtension(assemblyFilename, ".exportsymbols"));
1069+
if (!File.Exists(exportSymbolsFile))
1070+
Log.LogWarning($"EnableUnmanagedCallersOnlyMethodsExport is true, but no .exportsymbols file generated for assembly '{assemblyFilename}'. Check that the AOT compilation mode is full.");
1071+
}
1072+
}
1073+
10431074
private static IList<ITaskItem> ConvertAssembliesDictToOrderedList(ConcurrentDictionary<string, ITaskItem> dict, IList<ITaskItem> originalAssemblies)
10441075
{
10451076
List<ITaskItem> outItems = new(originalAssemblies.Count);

0 commit comments

Comments
 (0)