Opcja GCC-fPIC

Czytałem o opcjach GCC dla Konwencji generowania kodu , ale nie mogłem zrozumieć, co robi " Generowanie kodu niezależnego od pozycji (PIC)". Proszę podać przykład, który wyjaśni mi, co to oznacza.

Author: Hauke Rehfeld, 2011-03-15

6 answers

Kod niezależny od pozycji oznacza, że wygenerowany kod maszynowy nie jest zależny od położenia pod określonym adresem w celu działania.

Np. skoki będą generowane jako względne, a nie absolutne.

Pseudo-assembly:

PIC: to zadziała, czy kod będzie pod adresem 100 czy 1000

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL CURRENT+10
...
111: NOP

Non-PIC: to zadziała tylko wtedy, gdy kod jest pod adresem 100

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL 111
...
111: NOP

EDIT: w odpowiedzi na komentarz.

Jeśli kod jest kompilowany z-fPIC, nadaje się do włączenia do biblioteki - biblioteka musi być w stanie zostać przeniesiona z preferowanej lokalizacji w pamięci na inny adres, może być inna już załadowana biblioteka pod adresem preferowanym przez Bibliotekę.

 399
Author: Erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-08 00:04:14

Postaram się wyjaśnić to, co już zostało powiedziane w prostszy sposób.

Za każdym razem, gdy współdzielona lib jest ładowana, loader (kod systemu operacyjnego, który ładuje dowolny uruchomiony program) zmienia niektóre adresy w kodzie w zależności od tego, gdzie obiekt został załadowany.

W powyższym przykładzie, "111" w kodzie nie-PIC jest zapisywany przez loader przy pierwszym załadowaniu.

Dla obiektów nie współdzielonych, możesz chcieć, aby tak było, ponieważ kompilator może dokonać pewnych optymalizacji na ten kod.

Dla obiektu współdzielonego, jeśli inny proces będzie chciał "połączyć" się z tym kodem, musi go odczytać pod tymi samymi wirtualnymi adresami, inaczej "111" nie będzie miało sensu. ale ta wirtualna przestrzeń może być już używana w drugim procesie.

 45
Author: Roee Gavirel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 17:47:51

Kod wbudowany w biblioteki współdzielone powinien normalnie być kodem niezależnym od pozycji, tak aby biblioteka współdzielona mogła być łatwo załadowana pod (mniej więcej) dowolnym adresem w pamięci. Opcja -fPIC zapewnia, że GCC wytworzy taki kod.

 30
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 12:25:13

Dodawanie dalej...

Każdy proces ma taką samą wirtualną przestrzeń adresową (jeśli randomizacja wirtualnego adresu zostanie zatrzymana przez użycie flagi w systemie linux) (Aby uzyskać więcej informacji Wyłącz i ponownie włącz randomizację układu przestrzeni adresowej tylko dla siebie )

Więc jeśli jego jeden exe bez współdzielonego linkowania (hipotetyczny scenariusz), to zawsze możemy dać ten sam wirtualny adres tej samej instrukcji asm bez szkody.

Ale gdy chcemy połączyć obiekt współdzielony z exe, to jesteśmy nie jestem pewien adresu początkowego przypisanego do obiektu współdzielonego, ponieważ zależy to od kolejności, w jakiej obiekty współdzielone zostały połączone.To powiedziawszy, Instrukcja ASM inside. so zawsze będzie miał inny adres wirtualny w zależności od procesu, do którego się łączy.

Więc jeden proces może podać adres startowy .tak jak 0x45678910 w swojej wirtualnej przestrzeni, a inny proces w tym samym czasie może podać adres startowy 0x12131415 i jeśli nie użyją adresacji względnej,. so nie będzie działać w wszystkie.

Więc zawsze muszą używać trybu adresowania względnego, a co za tym idzie opcji fpic.

 16
Author: Ritesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:47

Łącze do funkcji w bibliotece dynamicznej jest rozwiązywane po załadowaniu biblioteki lub w czasie jej uruchomienia. Dlatego zarówno plik wykonywalny, jak i biblioteka dynamiczna są ładowane do pamięci po uruchomieniu programu. Adres pamięci, pod którym ładowana jest biblioteka dynamiczna, nie może być określony w advance, ponieważ stały adres może kolidować z inną dynamiczną biblioteką wymagającą tego samego adresu.


Istnieją dwie powszechnie stosowane metody radzenia sobie z tym problem:

1.Przeniesienie. Wszystkie wskaźniki i adresy w kodzie są modyfikowane, jeśli to konieczne, aby pasowały do rzeczywistego adresu ładowania. Przenoszenie odbywa się przez łącznik i ładowarkę.

2.Kod niezależny od pozycji. Wszystkie adresy w kodzie są względem bieżącej pozycji. Obiekty współdzielone w systemach uniksopodobnych domyślnie używają kodu zależnego od pozycji. Jest to mniej wydajne niż Relokacja, jeśli program działa przez długi czas, zwłaszcza w trybie 32-bitowym.


Nazwa " Kod niezależny od pozycji " W rzeczywistości implikuje następujące:

  • Sekcja kodu nie zawiera adresów bezwzględnych, które wymagają relokacji, a jedynie self relative adresy. Dlatego sekcja kodu może być załadowana pod dowolnym adresem pamięci i współdzielona między wieloma procesami.

  • Sekcja danych nie jest współdzielona między wieloma procesami, ponieważ często zawiera dane do zapisu. Dlatego sekcja danych może zawierać wskaźniki lub adresy że potrzebuję przeniesienia.

  • Wszystkie publiczne funkcje i publiczne dane mogą być nadpisywane w Linuksie. Jeśli funkcja w głównym pliku wykonywalnym ma taką samą nazwę jak funkcja w obiekcie współdzielonym, wtedy wersja W main będzie miała pierwszeństwo, nie tylko gdy zostanie wywołana z main, ale także gdy wywołane z obiektu współdzielonego. Podobnie, gdy zmienna globalna W main ma taką samą nazwa jako zmienna globalna w obiekcie współdzielonym, wtedy instancja w main będzie używane, nawet gdy dostępne z udostępnionego obiekt.


Ta tak zwana interppozycja symboli ma na celu naśladowanie zachowania bibliotek statycznych.

Obiekt współdzielony ma tabelę wskaźników do swoich funkcji, zwaną tabelą połączeń (PLT) oraz tabelą w celu zaimplementowania tej funkcji "override" należy użyć wskaźników do zmiennych o nazwie global offset table (GOT). Wszystkie dostępy do funkcji i zmiennych publicznych przechodzą przez te tabele.

P. S. gdzie dynamicznego linkowania nie da się uniknąć, są różne sposoby na uniknięcie czasuprzykładne cechy kodu zależnego od pozycji.

Możesz przeczytać więcej z tego artykułu: http://www.agner.org/optimize/optimizing_cpp.pdf

 7
Author: bruziuz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-24 11:30:44

Drobny dodatek do już opublikowanych odpowiedzi: pliki obiektowe nie skompilowane jako niezależne od pozycji są relokowalne; zawierają wpisy w tabeli relokacji.

Te wpisy pozwalają loaderowi (temu bitowi kodu, który ładuje program do pamięci) przepisać adresy bezwzględne, aby dostosować rzeczywisty adres ładowania w wirtualnej przestrzeni adresowej.

System operacyjny będzie próbował udostępnić jedną kopię" shared object library " załadowaną do pamięci ze wszystkimi programami, które są połączone z tą samą biblioteką obiektów współdzielonych.

Ponieważ przestrzeń adresowa kodu (w przeciwieństwie do sekcji przestrzeni danych) nie musi być sąsiadująca ze sobą, a ponieważ większość programów łączących się z konkretną biblioteką ma dość stałe drzewo zależności bibliotek, przez większość czasu odnosi to sukces. W rzadkich przypadkach, gdy istnieje rozbieżność, tak, może być konieczne posiadanie dwóch lub więcej kopii biblioteki obiektów współdzielonych w pamięci.

Oczywiście każda próba randomizacji adresu ładowania biblioteki pomiędzy programami i / lub instancjami programu (tak aby zmniejszyć możliwość tworzenia exploitowalnego wzorca) sprawią, że takie przypadki będą powszechne, a nie rzadkie, więc jeśli system włączył tę możliwość, należy podjąć każdą próbę kompilacji wszystkich bibliotek obiektów współdzielonych, aby były niezależne od pozycji.

Ponieważ wywołania do tych bibliotek z ciała głównego programu również będą relokowalne, to znacznie zmniejsza prawdopodobieństwo, że biblioteka współdzielona będzie musiała zostać skopiowana.

 4
Author: user1016759,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-15 21:48:08