From f429780c9ccce3546e9c9e25c05ed083318428bd Mon Sep 17 00:00:00 2001 From: Ivan Povazan <55002338+ivanpovazan@users.noreply.github.com> Date: Thu, 19 Jan 2023 11:17:02 +0100 Subject: [PATCH] [mono] Prefix exported symbols via UnmanagedCallersOnly attribute (#79880) Fixes https://github.com/dotnet/runtime/issues/79491 --- src/mono/mono/mini/aot-compiler.c | 6 +- .../ILLink.Descriptors.xml | 8 ++ .../Device/ExportManagedSymbols/Program.cs | 25 +++++ ...OS.Device.ExportManagedSymbols.Test.csproj | 23 ++++ .../iOS/Device/ExportManagedSymbols/main.m | 106 ++++++++++++++++++ 5 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/ILLink.Descriptors.xml create mode 100644 src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/Program.cs create mode 100644 src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/iOS.Device.ExportManagedSymbols.Test.csproj create mode 100644 src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/main.m diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index cf7a164eb3e82..de1d1c5efa8c6 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5208,9 +5208,9 @@ MONO_RESTORE_WARNING for (j = 0; j < decoded_args->named_args_num; ++j) { if (decoded_args->named_args_info [j].field && !strcmp (decoded_args->named_args_info [j].field->name, "EntryPoint")) { named = (const char *)decoded_args->named_args[j]->value.primitive; - slen = mono_metadata_decode_value (named, &named); + slen = mono_metadata_decode_value (named, &named) + (int)strlen(acfg->user_symbol_prefix); export_name = (char *)g_malloc (slen + 1); - memcpy (export_name, named, slen); + sprintf (export_name, "%s%s", acfg->user_symbol_prefix, named); export_name [slen] = 0; } } @@ -5222,7 +5222,7 @@ MONO_RESTORE_WARNING add_method (acfg, wrapper); if (export_name) { g_hash_table_insert (acfg->export_names, wrapper, export_name); - g_string_append_printf (export_symbols, "%s%s\n", acfg->user_symbol_prefix, export_name); + g_string_append_printf (export_symbols, "%s\n", export_name); } } diff --git a/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/ILLink.Descriptors.xml b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/ILLink.Descriptors.xml new file mode 100644 index 0000000000000..863595682f8f9 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/ILLink.Descriptors.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/Program.cs b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/Program.cs new file mode 100644 index 0000000000000..510a752d5c1b4 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/Program.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +public static class Program +{ + [DllImport("__Internal")] + public static extern void mono_ios_set_summary (string value); + + [UnmanagedCallersOnly(EntryPoint="exposed_managed_method")] + public static int ManagedMethod() => 42; + + public static async Task Main(string[] args) + { + mono_ios_set_summary($"Starting functional test"); + Console.WriteLine("Done!"); + await Task.Delay(5000); + + return 42; + } +} diff --git a/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/iOS.Device.ExportManagedSymbols.Test.csproj b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/iOS.Device.ExportManagedSymbols.Test.csproj new file mode 100644 index 0000000000000..be52903a35524 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/iOS.Device.ExportManagedSymbols.Test.csproj @@ -0,0 +1,23 @@ + + + + Exe + false + true + true + $(NetCoreAppCurrent) + iOS + iOS.Device.ExportManagedSymbols.Test.dll + false + 42 + true + true + $(MSBuildProjectDirectory)/main.m + + + + + + + + diff --git a/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/main.m b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/main.m new file mode 100644 index 0000000000000..067a52edfbfdf --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Device/ExportManagedSymbols/main.m @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#import +#import +#import "runtime.h" +#include + +@interface ViewController : UIViewController +@end + +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) ViewController *controller; +@end + +@implementation AppDelegate +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.controller = [[ViewController alloc] initWithNibName:nil bundle:nil]; + self.window.rootViewController = self.controller; + [self.window makeKeyAndVisible]; + return YES; +} +@end + +UILabel *summaryLabel; +UITextView* logLabel; + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + CGRect applicationFrame = [[UIScreen mainScreen] bounds]; + logLabel = [[UITextView alloc] initWithFrame: + CGRectMake(2.0, 50.0, applicationFrame.size.width - 2.0, applicationFrame.size.height - 50.0)]; + logLabel.font = [UIFont systemFontOfSize:9.0]; + logLabel.backgroundColor = [UIColor blackColor]; + logLabel.textColor = [UIColor greenColor]; + logLabel.scrollEnabled = YES; + logLabel.alwaysBounceVertical = YES; +#ifndef TARGET_OS_TV + logLabel.editable = NO; +#endif + logLabel.clipsToBounds = YES; + + summaryLabel = [[UILabel alloc] initWithFrame: CGRectMake(10.0, 0.0, applicationFrame.size.width - 10.0, 50)]; + summaryLabel.textColor = [UIColor whiteColor]; + summaryLabel.font = [UIFont boldSystemFontOfSize: 12]; + summaryLabel.numberOfLines = 2; + summaryLabel.textAlignment = NSTextAlignmentLeft; +#if !TARGET_OS_SIMULATOR || FORCE_AOT + summaryLabel.text = @"Loading..."; +#else + summaryLabel.text = @"Jitting..."; +#endif + [self.view addSubview:logLabel]; + [self.view addSubview:summaryLabel]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + void *del = dlsym (RTLD_DEFAULT, "exposed_managed_method"); + NSAssert(del != NULL, @"'exposed_managed_method' not found"); + mono_ios_runtime_init (); + }); +} + +@end + +// called from C# +void +invoke_external_native_api (void (*callback)(void)) +{ + if (callback) + callback(); +} + +// can be called from C# to update UI +void +mono_ios_set_summary (const char* value) +{ + NSString* nsstr = [NSString stringWithUTF8String:value]; + dispatch_async(dispatch_get_main_queue(), ^{ + summaryLabel.text = nsstr; + }); +} + +// can be called from C# to update UI +void +mono_ios_append_output (const char* value) +{ + NSString* nsstr = [NSString stringWithUTF8String:value]; + dispatch_async(dispatch_get_main_queue(), ^{ + logLabel.text = [logLabel.text stringByAppendingString:nsstr]; + CGRect caretRect = [logLabel caretRectForPosition:logLabel.endOfDocument]; + [logLabel scrollRectToVisible:caretRect animated:NO]; + [logLabel setScrollEnabled:NO]; + [logLabel setScrollEnabled:YES]; + }); +} + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +}