Skip to content

Commit 40bc2d8

Browse files
authored
[mono][wasm] Fix function signature mismatch in m2n invoke (#101106)
Fix signature mismatch
1 parent 7d91bf5 commit 40bc2d8

File tree

13 files changed

+157
-64
lines changed

13 files changed

+157
-64
lines changed

src/mono/browser/runtime/runtime.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
int mono_wasm_enable_gc = 1;
6666

6767
/* Missing from public headers */
68+
char *mono_fixup_symbol_name (char *key);
6869
void mono_icall_table_init (void);
6970
void mono_wasm_enable_debugging (int);
7071
void mono_ee_interp_init (const char *opts);
@@ -213,13 +214,8 @@ get_native_to_interp (MonoMethod *method, void *extra_arg)
213214

214215
assert (strlen (name) < 100);
215216
snprintf (key, sizeof(key), "%s_%s_%s", name, class_name, method_name);
216-
len = strlen (key);
217-
for (int i = 0; i < len; ++i) {
218-
if (key [i] == '.')
219-
key [i] = '_';
220-
}
221-
222-
addr = wasm_dl_get_native_to_interp (key, extra_arg);
217+
char* fixedName = mono_fixup_symbol_name(key);
218+
addr = wasm_dl_get_native_to_interp (fixedName, extra_arg);
223219
MONO_EXIT_GC_UNSAFE;
224220
return addr;
225221
}

src/mono/mono/metadata/native-library.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,3 +1222,32 @@ mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn)
12221222
{
12231223
pinvoke_override = override_fn;
12241224
}
1225+
1226+
// Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs
1227+
char* mono_fixup_symbol_name (char *key) {
1228+
char* fixedName = malloc(256);
1229+
int sb_index = 0;
1230+
int len = (int)strlen (key);
1231+
1232+
for (int i = 0; i < len; ++i) {
1233+
unsigned char b = key[i];
1234+
if ((b >= '0' && b <= '9') ||
1235+
(b >= 'a' && b <= 'z') ||
1236+
(b >= 'A' && b <= 'Z') ||
1237+
(b == '_')) {
1238+
fixedName[sb_index++] = b;
1239+
}
1240+
else if (b == '.' || b == '-' || b == '+' || b == '<' || b == '>') {
1241+
fixedName[sb_index++] = '_';
1242+
}
1243+
else {
1244+
// Append the hexadecimal representation of b between underscores
1245+
sprintf(&fixedName[sb_index], "_%X_", b);
1246+
sb_index += 4; // Move the index after the appended hexadecimal characters
1247+
}
1248+
}
1249+
1250+
// Null-terminate the fixedName string
1251+
fixedName[sb_index] = '\0';
1252+
return fixedName;
1253+
}

src/mono/mono/metadata/native-library.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,7 @@ mono_lookup_pinvoke_qcall_internal (const char *name);
3535
void
3636
mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn);
3737

38+
char *
39+
mono_fixup_symbol_name (char *key);
40+
3841
#endif

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <mono/metadata/mempool-internals.h>
5252
#include <mono/metadata/mono-basic-block.h>
5353
#include <mono/metadata/mono-endian.h>
54+
#include <mono/metadata/native-library.h>
5455
#include <mono/metadata/threads-types.h>
5556
#include <mono/metadata/custom-attrs-internals.h>
5657
#include <mono/utils/mono-logger-internals.h>
@@ -12407,22 +12408,24 @@ emit_file_info (MonoAotCompile *acfg)
1240712408

1240812409
if (acfg->aot_opts.static_link) {
1240912410
char symbol [MAX_SYMBOL_SIZE];
12410-
char *p;
1241112411

1241212412
/*
1241312413
* Emit a global symbol which can be passed by an embedding app to
1241412414
* mono_aot_register_module (). The symbol points to a pointer to the file info
1241512415
* structure.
1241612416
*/
1241712417
sprintf (symbol, "%smono_aot_module_%s_info", acfg->user_symbol_prefix, acfg->image->assembly->aname.name);
12418-
12418+
#ifdef TARGET_WASM
12419+
acfg->static_linking_symbol = g_strdup (mono_fixup_symbol_name(symbol));
12420+
#else
1241912421
/* Get rid of characters which cannot occur in symbols */
12420-
p = symbol;
12422+
char *p = symbol;
1242112423
for (p = symbol; *p; ++p) {
1242212424
if (!(isalnum (*p) || *p == '_'))
1242312425
*p = '_';
1242412426
}
1242512427
acfg->static_linking_symbol = g_strdup (symbol);
12428+
#endif
1242612429
}
1242712430

1242812431
if (acfg->llvm)
@@ -14860,7 +14863,6 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1486014863
{
1486114864
MonoImage *image = ass->image;
1486214865
MonoAotCompile *acfg;
14863-
char *p;
1486414866
int res;
1486514867
TV_DECLARE (atv);
1486614868
TV_DECLARE (btv);
@@ -15120,13 +15122,17 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1512015122
acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_ONLY);
1512115123

1512215124
acfg->assembly_name_sym = g_strdup (get_assembly_prefix (acfg->image));
15123-
/* Get rid of characters which cannot occur in symbols */
15125+
#ifdef TARGET_WASM
15126+
acfg->global_prefix = g_strdup_printf ("mono_aot_%s", g_strdup(mono_fixup_symbol_name (acfg->assembly_name_sym)));
15127+
#else
15128+
char *p;
15129+
/* Get rid of characters which cannot occur in symbols */
1512415130
for (p = acfg->assembly_name_sym; *p; ++p) {
1512515131
if (!(isalnum (*p) || *p == '_'))
1512615132
*p = '_';
1512715133
}
15128-
1512915134
acfg->global_prefix = g_strdup_printf ("mono_aot_%s", acfg->assembly_name_sym);
15135+
#endif
1513015136
acfg->plt_symbol = g_strdup_printf ("%s_plt", acfg->global_prefix);
1513115137
acfg->got_symbol = g_strdup_printf ("%s_got", acfg->global_prefix);
1513215138
if (acfg->llvm) {

src/mono/mono/mini/mini-llvm.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <mono/metadata/debug-helpers.h>
1313
#include <mono/metadata/debug-internals.h>
1414
#include <mono/metadata/mempool-internals.h>
15+
#include <mono/metadata/native-library.h>
1516
#include <mono/metadata/environment.h>
1617
#include <mono/metadata/object-internals.h>
1718
#include <mono/metadata/abi-details.h>
@@ -14519,17 +14520,21 @@ emit_aot_file_info (MonoLLVMModule *module)
1451914520
LLVMSetInitializer (info_var, LLVMConstNamedStruct (module->info_var_type, fields, nfields));
1452014521

1452114522
if (module->static_link) {
14522-
char *s, *p;
14523+
char *s;
1452314524
LLVMValueRef var;
1452414525

1452514526
s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name);
14527+
#ifdef TARGET_WASM
14528+
var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), g_strdup (mono_fixup_symbol_name(s)));
14529+
#else
1452614530
/* Get rid of characters which cannot occur in symbols */
14527-
p = s;
14531+
char *p = s;
1452814532
for (p = s; *p; ++p) {
1452914533
if (!(isalnum (*p) || *p == '_'))
14530-
*p = '_';
14534+
*p = '_';
1453114535
}
1453214536
var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), s);
14537+
#endif
1453314538
g_free (s);
1453414539
LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), pointer_type (LLVMInt8Type ())));
1453514540
LLVMSetLinkage (var, LLVMExternalLinkage);

src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ public static void AssertEqual(object expected, object actual, string label)
9191
$"[{label}]\n");
9292
}
9393

94-
private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' };
94+
private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' };
95+
// Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs
96+
// and with mono_fixup_symbol_name from src/mono/mono/metadata/native-library.c
9597
public static string FixupSymbolName(string name)
9698
{
9799
UTF8Encoding utf8 = new();

src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,5 +884,31 @@ public void EnsureWasmAbiRulesAreFollowedInAOT(BuildArgs buildArgs, RunHost host
884884
[BuildAndRun(host: RunHost.Chrome, aot: false)]
885885
public void EnsureWasmAbiRulesAreFollowedInInterpreter(BuildArgs buildArgs, RunHost host, string id) =>
886886
EnsureWasmAbiRulesAreFollowed(buildArgs, host, id);
887+
888+
[Theory]
889+
[BuildAndRun(host: RunHost.Chrome, aot: false)]
890+
public void UCOWithSpecialCharacters(BuildArgs buildArgs, RunHost host, string id)
891+
{
892+
var extraProperties = "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>";
893+
var extraItems = @"<NativeFileReference Include=""local.c"" />";
894+
895+
buildArgs = ExpandBuildArgs(buildArgs,
896+
extraItems: extraItems,
897+
extraProperties: extraProperties);
898+
899+
(string libraryDir, string output) = BuildProject(buildArgs,
900+
id: id,
901+
new BuildProjectOptions(
902+
InitProject: () =>
903+
{
904+
File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "UnmanagedCallback.cs"), Path.Combine(_projectDir!, "Program.cs"));
905+
File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "local.c"), Path.Combine(_projectDir!, "local.c"));
906+
},
907+
Publish: true,
908+
DotnetWasmFromRuntimePack: false));
909+
910+
var runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id);
911+
Assert.Contains("ManagedFunc returned 42", runOutput);
912+
}
887913
}
888914
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
public unsafe partial class Test
5+
{
6+
public unsafe static int Main(string[] args)
7+
{
8+
((IntPtr)(delegate* unmanaged<int,int>)&Interop.Managed8\u4F60Func).ToString();
9+
10+
Console.WriteLine($"main: {args.Length}");
11+
Interop.UnmanagedFunc();
12+
return 42;
13+
}
14+
}
15+
16+
file partial class Interop
17+
{
18+
[UnmanagedCallersOnly(EntryPoint = "ManagedFunc")]
19+
public static int Managed8\u4F60Func(int number)
20+
{
21+
// called from UnmanagedFunc
22+
Console.WriteLine($"Managed8\u4F60Func({number}) -> 42");
23+
return 42;
24+
}
25+
26+
[DllImport("local", EntryPoint = "UnmanagedFunc")]
27+
public static extern void UnmanagedFunc(); // calls ManagedFunc
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <stdio.h>
2+
int ManagedFunc(int number);
3+
4+
void UnmanagedFunc()
5+
{
6+
int ret = 0;
7+
printf("UnmanagedFunc calling ManagedFunc\n");
8+
ret = ManagedFunc(123);
9+
printf("ManagedFunc returned %d\n", ret);
10+
}

src/tasks/AotCompilerTask/MonoAOTCompiler.cs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,26 +1237,7 @@ private string FixupSymbolName(string name)
12371237
if (_symbolNameFixups.TryGetValue(name, out string? fixedName))
12381238
return fixedName;
12391239

1240-
UTF8Encoding utf8 = new();
1241-
byte[] bytes = utf8.GetBytes(name);
1242-
StringBuilder sb = new();
1243-
1244-
foreach (byte b in bytes)
1245-
{
1246-
if ((b >= (byte)'0' && b <= (byte)'9') ||
1247-
(b >= (byte)'a' && b <= (byte)'z') ||
1248-
(b >= (byte)'A' && b <= (byte)'Z') ||
1249-
(b == (byte)'_'))
1250-
{
1251-
sb.Append((char)b);
1252-
}
1253-
else
1254-
{
1255-
sb.Append('_');
1256-
}
1257-
}
1258-
1259-
fixedName = sb.ToString();
1240+
fixedName = Utils.FixupSymbolName(name);
12601241
_symbolNameFixups[name] = fixedName;
12611242
return fixedName;
12621243
}

0 commit comments

Comments
 (0)