2012-03-31 3 views
3

Я пытаюсь написать абстракцию для загрузки динамических библиотек в Windows и Linux. В то время как на платформе Windows, все идет хорошо, я получаю SIGSEGV, когда я звоню dlopen:SIGSEGV, когда P/Invoking 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!"); 
     } 
    } 
} 

Выход следующий:

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. 
================================================================= 

Что происходит?

Моя версия glibc - 2.11.3, а время автономной работы - 2.6.3.

Для компиляции программы: mono-csc Main.cs Для запуска программы: ./Main.exe


Я только straced выполнения тестового приложения. Вот системные вызовы перед 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\[email protected]\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) --- 

Этот след генерируется путем вызова «strace /opt/mono-2.10/bin/mono ./DlopenTest.exe 2> strace»

Трассирование моно по умолчанию установки (2.6) почти аналогично, и это всегда сбой в той же точке ,

Как отладить это условие? У меня нет идей ... Может быть, dlopen - это просто оболочка, поэтому я могу назвать альтернативную функцию? Возможно, я выполняю mono 2.10 в неправильной среде (может быть, мне нужно указать какую-либо переменную среды, чтобы получить эту работу)?

+1

Я бы помог вам отлаживать это, если бы вы обеспечили * полный * тест, и инструкции о том, как строить. Подсказка: немногие люди, которые знают о внутренностях dlopen, также знают, как писать код 'C#. –

+0

Обновлен вопрос. Чтение о dlopen кода кажется разумным, и о параметрах сортировки я пробовал почти все комбинации. – Luca

+0

Выведите отчет об ошибке, ваш код работает для меня. –

ответ

3

Ваш код работает над 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! 

Кажется, он не под 2.6 (это то, что довольно часто), но эта версия, если много лет ... Я настоятельно рекомендую вам обновить.

+1

Также работает для меня с использованием компилятора Mono JIT версии 2.4.4 (Debian 2.4.4 ~ svn151842-1ubuntu4) ' –

+0

Что довольно часто (в то же время, делая моно из источников). – Luca

+0

Модернизирован, но не повезло: он все равно падает. Будет ли проблема glibc? Я неохотно отношусь к этому варианту .... – Luca

2

Это хорошо известная ошибка во многих разных версиях Mono. Вот рабочее решение: https://bugzilla.xamarin.com/show_bug.cgi?id=4190

Вкратце: создайте простую оболочку в C/C++ для libdl.so (libfakedl.so) и коснитесь ее функций через оболочку.

Решено: http://s15.postimage.org/8x95bygh7/libdl_solved.png

+0

Я знаю, так как ошибка была открыта мной. – Luca

Смежные вопросы