2008-12-03 8 views

Odpowiedz

7

Jakiego poziomu szczegółowości potrzebujesz? Na poziomie podstawowym wszystkie dynamiczne linkery działają w podobny sposób:

  1. Dynamiczne biblioteki są kompilowane do relokowalnego kodu (na przykład za pomocą względnych skoków zamiast bezwzględnych).
  2. Łącznik znajduje puste miejsce o odpowiedniej wielkości w mapie pamięci aplikacji i odczytuje kod DLL i wszelkie statyczne dane do tego obszaru.
  3. Biblioteka dynamiczna zawiera tabelę przesunięć na początku każdej wyeksportowanej funkcji, a wywołania funkcji DLL w programie klienckim są załatwiane podczas ładowania z nowym adresem docelowym, w zależności od miejsca załadowania biblioteki.
  4. Większość dynamicznych systemów linkerów ma system do ustawiania preferowanego adresu bazowego dla konkretnej biblioteki. Jeśli biblioteka jest ładowana pod preferowanym adresem, wówczas przeniesienie w krokach 2 i 3 można pominąć.
+0

@ Mark Bessey. na poziomie maszyny :). Jak ładowarka wykonuje tę magię. Podobało mi się twoje oznaczenie i byłbym wdzięczny, gdyby mógł podać link/przykład zdekodowanego kodu m/c lub kodu asm, aby wyjaśnić bit. Nie spiesz się. :) – mahesh

2

Zakładając, że jest to w systemie Windows (wskazówki DLL na ten temat), może chcesz przeczytać stronę dokumentacji Microsoft Run-Time Dynamic Linking. Nie określa szczegółowo, w jaki sposób biblioteka DLL jest mapowana do przestrzeni adresowej; Chyba nie powinieneś tego wiedzieć.

+0

Odpręż się, już określiłem, że "jestem ciekawy". tylko ciekawy poziom @ m/c :). Dzięki za link. – mahesh

3

Jeśli jesteś naprawdę zainteresowany, przeczytaj książkę Linkers and Loaders.

+0

Dziękuję Ci D & C za ten najlepszy Link. – mahesh

9

OK, zakładam tu stronę Windows. Co się dzieje, kiedy załadować plik PE jest to, że ładowarka (zawarte w Ntdll) będzie wykonać następujące czynności:

  1. Zlokalizuj każdej z bibliotek DLL z wykorzystaniem semantyki wyszukiwania DLL (patch poziomie systemu i specyficzne), dobrze znany DLL są rodzajem zwolnione z tego
  2. mapie plik do pamięci (MMF), gdzie strony są kopiowanie przy zapisie (krowa),
  3. Traverse katalogu importu i za każdym uruchomieniu importu (rekurencyjnie) w punkcie 1.
  4. Dokonaj relokacji, która przez większość czasu jest tylko bardzo ograniczoną liczbą podmiotów, ponieważ sam kod jest niezależny od kodu (PIC)
  5. (IIRC) załatać EAT od RVA (względny wirtualny adres) do VA (wirtualny adres w bieżącym obszarze pamięci procesowej)
  6. Łata IAT (tabela adresów importu) w celu odniesienia do importów z ich faktycznym adresem w pamięci procesowej
  7. przypadku połączenia DLL DLLMain() do EXE tworzyć gwint początkowy, którego adres jest na wejściu pliku PE (w tym również uproszczony, ponieważ rzeczywisty adres początkowy znajduje się wewnątrz kernel32.dll procesów Win32)

Teraz podczas kompilacji kodu zależy od linkera, w jaki sposób odwołuje się funkcja zewnętrzna. Niektóre linkery tworzą stubs, więc - w teorii - próba sprawdzenia adresu funkcji przed NULL zawsze powie, że nie jest NULL. To dziwactwo, musisz wiedzieć, czy i kiedy twój linker zostanie naruszony.Inni odnoszą się bezpośrednio do wpisu IAT, w którym to przypadku adres URL funkcji bez odniesienia (myślę o opóźnionym załadowaniu) może mieć wartość NULL, a program obsługi SEH wywoła pomocnika opóźniającego ładowanie i (spróbuje) rozwiązać adres funkcji, zanim wznowi wykonywanie wskaż, że się nie udało.

W powyższy proces zaangażowanych jest wiele formalności, które uprościłem.

Istotą tego, co chciałeś wiedzieć, jest to, że w procesie mapowania dzieje jako MMF, choć można sztucznie naśladować zachowanie z przestrzeni sterty. Jednakże, jeśli pamiętasz o punkcie CoW, jest to sedno idei bibliotek DLL. Właściwie ta sama kopia (większości) stron DLL zostanie udostępniona wśród procesów, które ładują konkretną bibliotekę DLL. Strony, które nie są udostępniane, to te, do których pisaliśmy, na przykład przy rozwiązywaniu przeniesień i podobnych rzeczy. W takim przypadku każdy proces ma teraz - teraz zmodyfikowaną - kopię oryginalnej strony.

I słowo ostrzeżenia dotyczące pakerów EXE na DLL. Oni pokonują dokładnie ten mechanizm CoW, który opisałem, że alokują przestrzeń dla rozpakowanej zawartości DLL na stercie procesu, do którego ładowana jest biblioteka DLL. Tak więc, podczas gdy rzeczywista zawartość pliku jest nadal mapowana jako MMF i współużytkowana, rozpakowana zawartość zajmuje taką samą ilość pamięci dla każdego procesu ładowania biblioteki DLL zamiast jej udostępniania.

+0

Doskonałe wyjaśnienie dotyczące właściwości CoW bibliotek DLL. – shebaw

Powiązane problemy