Skip to content

Commit fe1269f

Browse files
committed
attempt fix dlopen error on some platforms (e.g. 32-bit linux)
1 parent d107dc4 commit fe1269f

File tree

1 file changed

+86
-18
lines changed

1 file changed

+86
-18
lines changed

Secp256k1.Net/DynamicLinking/DynamicLinkingLinux.cs

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ static class DynamicLinkingLinux
77
{
88
public const int RTLD_NOW = 2;
99

10-
// Try libdl first (glibc systems), fall back to libc (musl/Alpine)
10+
// libdl (works on most .NET Core Linux systems)
1111
[DllImport("libdl", EntryPoint = "dlopen")]
1212
private static extern IntPtr dlopen_libdl(string path, int flags);
1313
[DllImport("libdl", EntryPoint = "dlclose")]
@@ -17,7 +17,27 @@ static class DynamicLinkingLinux
1717
[DllImport("libdl", EntryPoint = "dlsym")]
1818
private static extern IntPtr dlsym_libdl(IntPtr handle, string name);
1919

20-
// On musl-based systems (Alpine), dlopen is in libc
20+
// libdl.so.2 (required for Mono on some glibc systems)
21+
[DllImport("libdl.so.2", EntryPoint = "dlopen")]
22+
private static extern IntPtr dlopen_libdl2(string path, int flags);
23+
[DllImport("libdl.so.2", EntryPoint = "dlclose")]
24+
private static extern int dlclose_libdl2(IntPtr handle);
25+
[DllImport("libdl.so.2", EntryPoint = "dlerror")]
26+
private static extern IntPtr dlerror_libdl2();
27+
[DllImport("libdl.so.2", EntryPoint = "dlsym")]
28+
private static extern IntPtr dlsym_libdl2(IntPtr handle, string name);
29+
30+
// libc.so.6 (fallback for glibc systems where dlopen moved to libc)
31+
[DllImport("libc.so.6", EntryPoint = "dlopen")]
32+
private static extern IntPtr dlopen_libc6(string path, int flags);
33+
[DllImport("libc.so.6", EntryPoint = "dlclose")]
34+
private static extern int dlclose_libc6(IntPtr handle);
35+
[DllImport("libc.so.6", EntryPoint = "dlerror")]
36+
private static extern IntPtr dlerror_libc6();
37+
[DllImport("libc.so.6", EntryPoint = "dlsym")]
38+
private static extern IntPtr dlsym_libc6(IntPtr handle, string name);
39+
40+
// libc (musl/Alpine systems)
2141
[DllImport("libc", EntryPoint = "dlopen")]
2242
private static extern IntPtr dlopen_libc(string path, int flags);
2343
[DllImport("libc", EntryPoint = "dlclose")]
@@ -27,36 +47,84 @@ static class DynamicLinkingLinux
2747
[DllImport("libc", EntryPoint = "dlsym")]
2848
private static extern IntPtr dlsym_libc(IntPtr handle, string name);
2949

30-
private static readonly bool UseLibdl = ProbeLibdl();
50+
private enum DlLibrary { Libdl, Libdl2, Libc6, Libc }
51+
private static readonly DlLibrary ActiveLibrary = ProbeLibrary();
3152

32-
private static bool ProbeLibdl()
53+
private static DlLibrary ProbeLibrary()
3354
{
55+
// Try libdl (most .NET Core systems)
3456
try
3557
{
3658
dlopen_libdl(null, RTLD_NOW);
37-
return true;
59+
return DlLibrary.Libdl;
3860
}
39-
catch (DllNotFoundException)
61+
catch (DllNotFoundException) { }
62+
catch (EntryPointNotFoundException) { }
63+
64+
// Try libdl.so.2 (Mono on glibc)
65+
try
4066
{
41-
return false;
67+
dlopen_libdl2(null, RTLD_NOW);
68+
return DlLibrary.Libdl2;
4269
}
43-
catch (EntryPointNotFoundException)
70+
catch (DllNotFoundException) { }
71+
catch (EntryPointNotFoundException) { }
72+
73+
// Try libc.so.6 (newer glibc where dlopen moved to libc)
74+
try
4475
{
45-
// On some 32-bit Linux systems, libdl exists but dlopen is only in libc
46-
return false;
76+
dlopen_libc6(null, RTLD_NOW);
77+
return DlLibrary.Libc6;
4778
}
79+
catch (DllNotFoundException) { }
80+
catch (EntryPointNotFoundException) { }
81+
82+
// Fall back to libc (musl/Alpine)
83+
return DlLibrary.Libc;
4884
}
4985

50-
public static IntPtr dlopen(string path, int flags) =>
51-
UseLibdl ? dlopen_libdl(path, flags) : dlopen_libc(path, flags);
86+
public static IntPtr dlopen(string path, int flags)
87+
{
88+
switch (ActiveLibrary)
89+
{
90+
case DlLibrary.Libdl: return dlopen_libdl(path, flags);
91+
case DlLibrary.Libdl2: return dlopen_libdl2(path, flags);
92+
case DlLibrary.Libc6: return dlopen_libc6(path, flags);
93+
default: return dlopen_libc(path, flags);
94+
}
95+
}
5296

53-
public static int dlclose(IntPtr handle) =>
54-
UseLibdl ? dlclose_libdl(handle) : dlclose_libc(handle);
97+
public static int dlclose(IntPtr handle)
98+
{
99+
switch (ActiveLibrary)
100+
{
101+
case DlLibrary.Libdl: return dlclose_libdl(handle);
102+
case DlLibrary.Libdl2: return dlclose_libdl2(handle);
103+
case DlLibrary.Libc6: return dlclose_libc6(handle);
104+
default: return dlclose_libc(handle);
105+
}
106+
}
55107

56-
public static IntPtr dlerror() =>
57-
UseLibdl ? dlerror_libdl() : dlerror_libc();
108+
public static IntPtr dlerror()
109+
{
110+
switch (ActiveLibrary)
111+
{
112+
case DlLibrary.Libdl: return dlerror_libdl();
113+
case DlLibrary.Libdl2: return dlerror_libdl2();
114+
case DlLibrary.Libc6: return dlerror_libc6();
115+
default: return dlerror_libc();
116+
}
117+
}
58118

59-
public static IntPtr dlsym(IntPtr handle, string name) =>
60-
UseLibdl ? dlsym_libdl(handle, name) : dlsym_libc(handle, name);
119+
public static IntPtr dlsym(IntPtr handle, string name)
120+
{
121+
switch (ActiveLibrary)
122+
{
123+
case DlLibrary.Libdl: return dlsym_libdl(handle, name);
124+
case DlLibrary.Libdl2: return dlsym_libdl2(handle, name);
125+
case DlLibrary.Libc6: return dlsym_libc6(handle, name);
126+
default: return dlsym_libc(handle, name);
127+
}
128+
}
61129
}
62130
}

0 commit comments

Comments
 (0)