I'm trying to write an abstraction to load dynamic libraries on Windows and Linux. While on Windows platform everything goes fine, I get a SIGSEGV when I call dlopen:
// File: Main.cs
using System;
using System.Runtime.InteropServices;
namespace DlopenTest
{
class MainClass
{
const int RTLD_NOW = 2;
[DllImport("dl")]
static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)] string filename, int flags);
[DllImport("dl")]
static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] string symbol);
public static void Main (string[] args)
{
IntPtr libraryHandle = dlopen("libc.so.6", RTLD_NOW);
Console.WriteLine ("Success!");
}
}
}
The output is the following:
Stacktrace:
at (wrapper managed-to-native) DlopenTest.MainClass.dlopen (string,int) <0x00004>
at (wrapper managed-to-native) DlopenTest.MainClass.dlopen (string,int) <0x00004>
at DlopenTest.MainClass.Main (string[]) [0x00000] in /home/luca/Projects/DlopenTest/DlopenTest/Main.cs:18
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x0001d, 0x00043>
Native stacktrace:
/usr/bin/mono() [0x80d5b19]
/usr/bin/mono() [0x810f7ab]
[0xb771940c]
/lib/ld-linux.so.2(+0x119a8) [0xb772b9a8]
/usr/lib/libdl.so(+0xc0b) [0xb536dc0b]
/lib/ld-linux.so.2(+0xdb36) [0xb7727b36]
/usr/lib/libdl.so(+0x109c) [0xb536e09c]
/usr/lib/libdl.so(dlopen+0x41) [0xb536db41]
[0xb58672f1]
[0xb58671bd]
[0xb5867234]
/usr/bin/mono() [0x8064428]
/usr/bin/mono(mono_runtime_invoke+0x40) [0x812d4e0]
/usr/bin/mono(mono_runtime_exec_main+0xde) [0x8130f8e]
/usr/bin/mono(mono_runtime_run_main+0x112) [0x8131292]
/usr/bin/mono(mono_main+0x15ec) [0x80b3bdc]
/usr/bin/mono() [0x805b675]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0xb74b8ca6]
/usr/bin/mono() [0x805b5b1]
Debug info from gdb:
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
What's going on?
My glibc version is 2.11.3, and the mono runtime is 2.6.3.
To compile the program: mono-csc Main.cs
To run the program: ./Main.exe
I've just straced the execution of the test application. Here is the system calls before the SIGSGV:
...
open("/usr/lib/libdl.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@\n\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=9736, ...}) = 0
mmap2(NULL, 12408, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb598b000
mmap2(0xb598d000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1) = 0xb598d000
close(3) = 0
mprotect(0xb598d000, 4096, PROT_READ) = 0
munmap(0xb598f000, 76774) = 0
gettimeofday({1333269422, 515602}, NULL) = 0
gettimeofday({1333269422, 515653}, NULL) = 0
gettimeofday({1333269422, 515828}, NULL) = 0
gettimeofday({1333269422, 515884}, NULL) = 0
gettimeofday({1333269422, 515986}, NULL) = 0
gettimeofday({1333269422, 516059}, NULL) = 0
gettimeofday({1333269422, 516613}, NULL) = 0
gettimeofday({1333269422, 516670}, NULL) = 0
brk(0x98e3000) = 0x98e3000
brk(0x98e1000) = 0x98e1000
gettimeofday({1333269422, 516916}, NULL) = 0
brk(0x98de000) = 0x98de000
brk(0x98dc000) = 0x98dc000
brk(0x98db000) = 0x98db000
gettimeofday({1333269422, 517092}, NULL) = 0
gettimeofday({1333269422, 517200}, NULL) = 0
gettimeofday({1333269422, 517261}, NULL) = 0
gettimeofday({1333269422, 517368}, NULL) = 0
gettimeofday({1333269422, 517525}, NULL) = 0
gettimeofday({1333269422, 517762}, NULL) = 0
gettimeofday({1333269422, 517823}, NULL) = 0
gettimeofday({1333269422, 518007}, NULL) = 0
gettimeofday({1333269422, 518074}, NULL) = 0
gettimeofday({1333269422, 518435}, NULL) = 0
gettimeofday({1333269422, 518486}, NULL) = 0
gettimeofday({1333269422, 518648}, NULL) = 0
gettimeofday({1333269422, 518699}, NULL) = 0
gettimeofday({1333269422, 518803}, NULL) = 0
futex(0xb598e06c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
This trace is generated by invoking "strace /opt/mono-2.10/bin/mono ./DlopenTest.exe 2> strace"
The strace of default mono installation (2.6) it almost similar, and it always crashing at the same point.
How to debug this condition? I'm out of ideas... Maybe dlopen is just a wrapper, so I can call an alternative function? Maybe I execute mono 2.10 in a wrong environement (maybe I have to specify some environment variable to get this work)?
Your code works on Mono 2.10.
$ mono --version
Mono JIT compiler version 2.10.5 (Debian 2.10.5-1)
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com
TLS: __thread
SIGSEGV: altstack
Notifications: epoll
Architecture: x86
Disabled: none
Misc: softdebug
LLVM: supported, not enabled.
GC: Included Boehm (with typed GC and Parallel Mark)
$ cat so.cs
using System;
using System.Runtime.InteropServices;
namespace DlopenTest
{
class MainClass
{
const int RTLD_NOW = 2;
[DllImport("dl")]
static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)] string filename, int flags);
[DllImport("dl")]
static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] string symbol);
public static void Main (string[] args)
{
IntPtr libraryHandle = dlopen("libc.so.6", RTLD_NOW);
Console.WriteLine ("Success!");
}
}
}
$ mcs so.cs
so.cs(18,20): warning CS0219: The variable `libraryHandle' is assigned but its value is never used
Compilation succeeded - 1 warning(s)
$ mono so.exe
Success!
It seems it failed under 2.6 (it's something pretty common) but that version if many years old... I strongly suggest you upgrade.
This is a well known bug in many different versions of Mono. Here is a working solution: https://bugzilla.xamarin.com/show_bug.cgi?id=4190
In short: create a simple wrapper in C/C++ for libdl.so ( libfakedl.so) and call its functions indirectly through the wrapper.
Solved: http://s15.postimage.org/8x95bygh7/libdl_solved.png
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With