Skip to content

Commit f429780

Browse files
authored
[mono] Prefix exported symbols via UnmanagedCallersOnly attribute (#79880)
Fixes #79491
1 parent b62bbdd commit f429780

File tree

5 files changed

+165
-3
lines changed

5 files changed

+165
-3
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5208,9 +5208,9 @@ MONO_RESTORE_WARNING
52085208
for (j = 0; j < decoded_args->named_args_num; ++j) {
52095209
if (decoded_args->named_args_info [j].field && !strcmp (decoded_args->named_args_info [j].field->name, "EntryPoint")) {
52105210
named = (const char *)decoded_args->named_args[j]->value.primitive;
5211-
slen = mono_metadata_decode_value (named, &named);
5211+
slen = mono_metadata_decode_value (named, &named) + (int)strlen(acfg->user_symbol_prefix);
52125212
export_name = (char *)g_malloc (slen + 1);
5213-
memcpy (export_name, named, slen);
5213+
sprintf (export_name, "%s%s", acfg->user_symbol_prefix, named);
52145214
export_name [slen] = 0;
52155215
}
52165216
}
@@ -5222,7 +5222,7 @@ MONO_RESTORE_WARNING
52225222
add_method (acfg, wrapper);
52235223
if (export_name) {
52245224
g_hash_table_insert (acfg->export_names, wrapper, export_name);
5225-
g_string_append_printf (export_symbols, "%s%s\n", acfg->user_symbol_prefix, export_name);
5225+
g_string_append_printf (export_symbols, "%s\n", export_name);
52265226
}
52275227
}
52285228

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<linker>
2+
<!-- this is here to show how to configure the trimming -->
3+
<assembly fullname="iOS.Device.ExportManagedSymbols.Test">
4+
<type fullname="Program">
5+
<method name="ManagedMethod" />
6+
</type>
7+
</assembly>
8+
</linker>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using System.Runtime.InteropServices;
8+
9+
public static class Program
10+
{
11+
[DllImport("__Internal")]
12+
public static extern void mono_ios_set_summary (string value);
13+
14+
[UnmanagedCallersOnly(EntryPoint="exposed_managed_method")]
15+
public static int ManagedMethod() => 42;
16+
17+
public static async Task<int> Main(string[] args)
18+
{
19+
mono_ios_set_summary($"Starting functional test");
20+
Console.WriteLine("Done!");
21+
await Task.Delay(5000);
22+
23+
return 42;
24+
}
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk" TreatAsLocalProperty="MonoForceInterpreter">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<MonoForceInterpreter>false</MonoForceInterpreter>
6+
<RunAOTCompilation>true</RunAOTCompilation>
7+
<TestRuntime>true</TestRuntime>
8+
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
9+
<TargetOS Condition="'$(TargetOS)' == ''">iOS</TargetOS>
10+
<MainLibraryFileName>iOS.Device.ExportManagedSymbols.Test.dll</MainLibraryFileName>
11+
<IncludesTestRunner>false</IncludesTestRunner>
12+
<ExpectedExitCode>42</ExpectedExitCode>
13+
<EnableAggressiveTrimming>true</EnableAggressiveTrimming>
14+
<MonoEnableLLVM>true</MonoEnableLLVM>
15+
<NativeMainSource>$(MSBuildProjectDirectory)/main.m</NativeMainSource>
16+
</PropertyGroup>
17+
18+
<ItemGroup>
19+
<Compile Include="Program.cs" />
20+
<!-- Prevent trimming of the exposed managed method via ILLinker -->
21+
<TrimmerRootDescriptor Include="$(MSBuildProjectDirectory)/ILLink.Descriptors.xml" />
22+
</ItemGroup>
23+
</Project>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#import <UIKit/UIKit.h>
5+
#import <dlfcn.h>
6+
#import "runtime.h"
7+
#include <TargetConditionals.h>
8+
9+
@interface ViewController : UIViewController
10+
@end
11+
12+
@interface AppDelegate : UIResponder <UIApplicationDelegate>
13+
@property (strong, nonatomic) UIWindow *window;
14+
@property (strong, nonatomic) ViewController *controller;
15+
@end
16+
17+
@implementation AppDelegate
18+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19+
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
20+
self.controller = [[ViewController alloc] initWithNibName:nil bundle:nil];
21+
self.window.rootViewController = self.controller;
22+
[self.window makeKeyAndVisible];
23+
return YES;
24+
}
25+
@end
26+
27+
UILabel *summaryLabel;
28+
UITextView* logLabel;
29+
30+
@implementation ViewController
31+
32+
- (void)viewDidLoad {
33+
[super viewDidLoad];
34+
35+
CGRect applicationFrame = [[UIScreen mainScreen] bounds];
36+
logLabel = [[UITextView alloc] initWithFrame:
37+
CGRectMake(2.0, 50.0, applicationFrame.size.width - 2.0, applicationFrame.size.height - 50.0)];
38+
logLabel.font = [UIFont systemFontOfSize:9.0];
39+
logLabel.backgroundColor = [UIColor blackColor];
40+
logLabel.textColor = [UIColor greenColor];
41+
logLabel.scrollEnabled = YES;
42+
logLabel.alwaysBounceVertical = YES;
43+
#ifndef TARGET_OS_TV
44+
logLabel.editable = NO;
45+
#endif
46+
logLabel.clipsToBounds = YES;
47+
48+
summaryLabel = [[UILabel alloc] initWithFrame: CGRectMake(10.0, 0.0, applicationFrame.size.width - 10.0, 50)];
49+
summaryLabel.textColor = [UIColor whiteColor];
50+
summaryLabel.font = [UIFont boldSystemFontOfSize: 12];
51+
summaryLabel.numberOfLines = 2;
52+
summaryLabel.textAlignment = NSTextAlignmentLeft;
53+
#if !TARGET_OS_SIMULATOR || FORCE_AOT
54+
summaryLabel.text = @"Loading...";
55+
#else
56+
summaryLabel.text = @"Jitting...";
57+
#endif
58+
[self.view addSubview:logLabel];
59+
[self.view addSubview:summaryLabel];
60+
61+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
62+
void *del = dlsym (RTLD_DEFAULT, "exposed_managed_method");
63+
NSAssert(del != NULL, @"'exposed_managed_method' not found");
64+
mono_ios_runtime_init ();
65+
});
66+
}
67+
68+
@end
69+
70+
// called from C#
71+
void
72+
invoke_external_native_api (void (*callback)(void))
73+
{
74+
if (callback)
75+
callback();
76+
}
77+
78+
// can be called from C# to update UI
79+
void
80+
mono_ios_set_summary (const char* value)
81+
{
82+
NSString* nsstr = [NSString stringWithUTF8String:value];
83+
dispatch_async(dispatch_get_main_queue(), ^{
84+
summaryLabel.text = nsstr;
85+
});
86+
}
87+
88+
// can be called from C# to update UI
89+
void
90+
mono_ios_append_output (const char* value)
91+
{
92+
NSString* nsstr = [NSString stringWithUTF8String:value];
93+
dispatch_async(dispatch_get_main_queue(), ^{
94+
logLabel.text = [logLabel.text stringByAppendingString:nsstr];
95+
CGRect caretRect = [logLabel caretRectForPosition:logLabel.endOfDocument];
96+
[logLabel scrollRectToVisible:caretRect animated:NO];
97+
[logLabel setScrollEnabled:NO];
98+
[logLabel setScrollEnabled:YES];
99+
});
100+
}
101+
102+
int main(int argc, char * argv[]) {
103+
@autoreleasepool {
104+
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
105+
}
106+
}

0 commit comments

Comments
 (0)