Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

Co prawda grupa dotyczy MS .NET, ale pewnie niejedna osoba dłubie coś pod Mono, więc może się przyda.

Przy okazji pisania większego projektu zaszła potrzeba załadowania pewnej biblioteki. Jakież było moje zdziwienie, gdy dostałem na dzień dobry po głowie SIGSEGVem... Początkowo myślałem, że problem wywołuje biblioteka, którą próbuję załadować. Ustawiałem wszystkie zmienne środowiskowe, z których potencjalnie mogła korzystać, uaktualniłem ldconfiga, przekompilowałem bibliotekę - nadal to samo.

Po chwili googlania okazało się, że nie jest to problem biblioteki, tylko Mono i dotyczy wielu różnych wersji. Jedni mają z tym problem, inni nie.

Tutaj, dla ilustracji, uproszczony przykład - ładowanie standardowej biblioteki C:


Obrazek


Wreszcie znalazłem rozwiązanie tego problemu. W skrócie - trzeba sobie napisać w C prostego wrappera do libdl.so i to do jego funkcji się odwoływać.

Nie wiem, podobnie jak autor, dlaczego to działa, ale działa:


Obrazek
Adrian Olszewski edytował(a) ten post dnia 05.11.12 o godzinie 01:56
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

Adrian Olszewski:
Co prawda grupa dotyczy MS .NET, ale pewnie niejedna osoba dłubie coś pod Mono, więc może się przyda.

Przy okazji pisania większego projektu zaszła potrzeba załadowania pewnej biblioteki. Jakież było moje zdziwienie, gdy dostałem na dzień dobry po głowie SIGSEGVem... Początkowo myślałem, że problem wywołuje biblioteka, którą próbuję załadować. Ustawiałem wszystkie zmienne środowiskowe, z których potencjalnie mogła korzystać, uaktualniłem ldconfiga, przekompilowałem bibliotekę - nadal to samo.

Po chwili googlania okazało się, że nie jest to problem biblioteki, tylko Mono i dotyczy wielu różnych wersji. Jedni mają z tym problem, inni nie.

Tutaj, dla ilustracji, uproszczony przykład - ładowanie standardowej biblioteki C:


Obrazek


Wreszcie znalazłem rozwiązanie tego problemu. W skrócie - trzeba sobie napisać w C prostego wrappera do libdl.so i to do jego funkcji się odwoływać.

Nie wiem, podobnie jak autor, dlaczego to działa, ale działa:


Obrazek
Od razu napiszę, że nic w Mono nie developowałem ;), więc moje pytanie może być bez sensu, ale:
próbowałeś wołać tą bibliotekę i ustawiać atrybuty CharSet oraz CallingConvention. Tak na moje przeczucie, ten wrapper może wszystko ustawia standardowo dla platformy linux i przez to udaje się import.

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

Ten wrapper to nic innego, jak wystawienie tych samych funkcji (m.in. dlopen) natywnej biblioteki libdl.so, bez żadnych zmian. Gdyby to było takie proste, nie siedziałbym nad tym zachodząc w głowę WTF :) Problem dotyczy dowolnej biblioteki .so. Powiedzmy, że to "odwołanie przez odwołanie" :)

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

void* my_dlopen(const char* file, int flag) {
void* ret;
ret = dlopen(file,flag);
return ret;
}

char* my_dlerror() {
char* err;
err = dlerror();
return err;
}

void* my_dlsym(void* handle, const char* symbol) {
void* ret;
ret = dlsym(handle,symbol);
return ret;
}

int my_dlclose(void* handle) {
return dlclose(handle);
}
Adrian Olszewski edytował(a) ten post dnia 05.11.12 o godzinie 11:22
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

Adrian Olszewski:
Ten wrapper to nic innego, jak wystawienie tych samych funkcji (m.in. dlopen) natywnej biblioteki libdl.so, bez żadnych zmian. Gdyby to było takie proste, nie siedziałbym nad tym zachodząc w głowę WTF :) Problem dotyczy dowolnej biblioteki .so. Powiedzmy, że to "odwołanie przez odwołanie" :)

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

void* my_dlopen(const char* file, int flag) {
void* ret;
ret = dlopen(file,flag);
return ret;
}

char* my_dlerror() {
char* err;
err = dlerror();
return err;
}

void* my_dlsym(void* handle, const char* symbol) {
void* ret;
ret = dlsym(handle,symbol);
return ret;
}

int my_dlclose(void* handle) {
return dlclose(handle);
}
Ale ten wrapper jest kompilowany jakimś standardowym kompilatorem?

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

gcc :)
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

Adrian Olszewski:
gcc :)
No to ciekawostka :)
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Rozwiązanie dla SIGSEGV przy dlopen pod Mono (2-10.8)

A w Linuxie jest tak, że można wymusić ładownie bibliotek/procesów od górnego do dolnego zakresu pamięci? Tzn. żeby wymusić używanie 64bitowego wskaźnika od razu. Ciekawe, czy by się sypała każda biblioteka ładowana przez PInvoke, która trafia od razu do górnego zakresu adresowania.

Taki strzał na oślep ;)

Następna dyskusja:

Warsztat pracy dla programu...




Wyślij zaproszenie do