W strace
wyjściach ścieżki do bibliotek wywoływanych przez pliki wykonywalne znajdują się w wywołaniach open()
. Czy jest to wywołanie systemowe używane przez pliki wykonywalne, które są dynamicznie połączone? Co dlopen()
? open()
nie jest to połączenie, które, jak przypuszczam, odegra pewną rolę w wykonywaniu programów.
23
ld-linux
jest mapowany przez jądro jako częśćexecve
wywołania systemowego.dlopen nie ma nic wspólnego z bibliotekami współdzielonymi, o których myślisz. Istnieją dwie metody ładowania obiektu udostępnionego:
main
wywołaniem funkcji i skonfiguruje przestrzeń procesową aplikacji, aby aplikacja znalazła funkcje biblioteki. Wymagaopen()
to włożenia smarowania, a następnie włożeniammap()
go, a następnie skonfigurowania niektórych tabel odnośników.libdl
, z którego następnie (za pomocą pierwszej metody) może wywołaćdlopen()
idlsym()
Funkcje. Z dlopen dostajesz uchwyt do biblioteki, której możesz następnie użyć z dlsym, aby otrzymać wskaźnik funkcji do określonej funkcji. Ta metoda jest o wiele bardziej skomplikowana dla programisty niż pierwsza metoda (ponieważ musisz wykonać konfigurację ręcznie, a nie linker robi to za ciebie automatycznie), a także jest bardziej delikatna (ponieważ nie dostajesz kompilacji -time sprawdza, czy wywołujesz funkcje z poprawnymi typami argumentów, jak w pierwszej metodzie), ale zaletą jest to, że możesz zdecydować, który obiekt współdzielony ma zostać załadowany w czasie wykonywania (lub nawet czy w ogóle go załadować), dzięki czemu jest to interfejs przeznaczony do funkcji typu wtyczek. Wreszcie interfejs dlopen jest również mniej przenośny niż w inny sposób, ponieważ jego mechanika zależy od dokładnej implementacji dynamicznego linkera (stąd libtool'slibltdl
, który próbuje pozbyć się tych różnic).źródło
Obecnie większość systemów operacyjnych korzysta z metody bibliotek współdzielonych wprowadzonej pod koniec 1987 roku przez SunOS-4.0. Ta metoda opiera się na mapowaniu pamięci za pomocą mmap ().
Biorąc pod uwagę fakt, że na początku lat 90. firma Sun przekazała nawet stary kod oparty na a.out (w tym czasie Solaris był już oparty na ELF) ludziom FreeBSD i że ten kod został później przekazany wielu innym systemom (w tym Linuxowi) , możesz zrozumieć, dlaczego nie ma dużej różnicy między platformami.
źródło
ltrace -S
analiza minimalnego przykładu pokazuje, żemmap
jest używany w glibc 2.23W glibc 2.23, Ubuntu 16.04, działający
latrace -S
na minimalnym programie, który używadlopen
z:przedstawia:
więc natychmiast widzimy, że
dlopen
wzywaopen
+mmap
.To niesamowite
ltrace
narzędzie śledzi zarówno wywołania biblioteki, jak i wywołania systemowe, dlatego idealnie nadaje się do sprawdzenia, co się dzieje w tym przypadku.Bliższa analiza pokazuje, że
open
zwraca deskryptor pliku3
(następny wolny po stdin, out i err).read
następnie używa tego deskryptora pliku, ale TODO, dlaczegommap
argumenty są ograniczone do czterech, i nie możemy zobaczyć, który fd został tam użyty, ponieważ jest to piąty argument .strace
potwierdza zgodnie z oczekiwaniami, że3
jest to jeden, i porządek wszechświata jest przywrócony.Dzielne dusze mogą również odważyć się na kod glibc, ale nie mogłem znaleźć
mmap
szybkiego grepa i jestem leniwy.Przetestowano na tym minimalnym przykładzie z kompilacją płyty grzewczej na GitHub .
źródło
strace
raporty o wywołaniach systemowych (tj. funkcjach implementowanych bezpośrednio przez jądro). Biblioteki dynamiczne nie są funkcją jądra;dlopen
jest częścią biblioteki C, a nie jądra. Implementacjadlopen
will callopen
(która jest wywołaniem systemowym), aby otworzyć plik biblioteki, aby można go było odczytać.źródło
ltrace
.ltrace -S
doskonale nadaje się do analizy tego, ponieważ pokazuje także syscalls: unix.stackexchange.com/a/462710/32558