2013-12-17 10 views
8

Na komputerach docelowych gcc, gdy ktoś chciał skompilować bibliotekę współużytkowaną, musiałby podać -fpic lub -fPIC, aby poprawić działanie. Wynika to z faktu, że domyślnie używane było adresowanie bezwzględne, które nadaje się do plików wykonywalnych, które mają pełną kontrolę nad własną przestrzenią adresową, ale nie dzielą się bibliotekami, które mogłyby być ładowane w dowolnym miejscu w przestrzeni adresowej pliku wykonywalnego.Czy nadal trzeba używać -fPIC podczas kompilacji z GCC?

Jednak współczesne jądra wdrażają teraz randomizację przestrzeni adresowej, a wiele nowoczesnych architektur obsługuje adresowanie względne komputera. Wszystko to sprawia, że ​​adresowanie bezwzględne nie nadaje się do użytku (randomizacja przestrzeni adresowej) lub niepotrzebne (adresowanie względne komputera osobistego).

Zauważyłem również, że klang nie ma opcji -fPIC, co czyni mnie rzeczą, która nie jest już potrzebna.

Czy więc -fpic jest teraz zbędny, czy trzeba wygenerować osobne pliki .o, jeden do korzystania z biblioteki statycznej i jeden do korzystania z biblioteki współdzielonej?

Odpowiedz

0

Nigdy nie trzeba generować oddzielnych plików .o. Zawsze określaj opcje kompilatora do generowania kodu przenośnego (zazwyczaj -fPIC).

W niektórych systemach kompilator może być skonfigurowany do wymuszania tej opcji lub do jej domyślnego ustawienia. Ale i tak nie zaszkodzi to określić.

Uwaga: Istnieje nadzieja, że ​​w miejscu, w którym adresowanie z komputera jest obsługiwane, , i działa dobrze, to znaczy, że -fPIC używa tego trybu zamiast dedykować dodatkowy rejestr.

+0

Kod PIC jest w większości przypadków wolniejszy, ponieważ dodatkowe przeskakiwanie przez PLT wymaga dodatkowego ograniczenia w przypadku wielu wywołań funkcji. Dobrym pomysłem jest budowanie bibliotek statycznych bez PIC. – Art

+0

@Art: Może być wolniejszy, ale nie za dużo. I nie zgadzam się, że warto budować statyczne biblioteki bez. Biblioteki statyczne są nie tylko połączone z plikami wykonywalnymi, ale także z bibliotekami współdzielonymi. I, jak wspomniano, pliki wykonywalne ASLR muszą być niezależne od pozycji. Najbezpieczniej jest więc zawsze podawać '-fPIC'. –

+0

@Art Problem na Intel nie jest wywołaniem funkcji lub skoków (które i tak są związane z PC), ale dostęp do danych globalnych. (W przypadku innych procesorów problemy będą się różnić.) –

1

Zgadzam się z wami w wielu przypadkach -fPIC/-fPIC opcje są prawie zbędne, ja jednak z nich korzystać, aby zapewnić:

  • przenoszenia (nie jestem pewien, co szczególnie OS/kernel będzie dostępny)
  • wsteczną kompatybilność z tych opcji: gwarantuje to zachowanie, które chcesz na starszych jąder
  • zwyczaj - twarde rzeczy złamać :)
  • zgodność ze starszymi codebases które mogą wymagać jej
5

Nadal trzeba kompilować z opcją -fPIC. Problem nie jest rozwiązywany za pomocą adresowania komputerowego. Problem polega na tym, w jaki sposób rozwiązujesz zewnętrzne symbole. W dynamicznie połączonym programie rozdzielczość jest zgodna z różnymi regułami, a zwłaszcza z randomizacją przestrzeni adresowej, której nie można rozwiązać w czasie połączenia.

A clang ma flagę -fPIC podobnie jak gcc.

$ cat > foo.c 
void foo(void); 
void bar(void) { foo(); } 
$ gcc -S foo.c && grep call.*foo foo.s 
    call foo 
$ gcc -fPIC -S foo.c && grep call.*foo foo.s 
    call [email protected] 
$ clang -S foo.c && grep call.*foo foo.s 
    callq foo 
$ clang -fPIC -S foo.c && grep call.*foo foo.s 
    callq [email protected] 
$ 
+1

Dobrze -fPIC, którego nie ma w instrukcji – doron

+0

@doron Myślę, że jest (ale być może nie było z powrotem w 2013 r.): Https://clang.llvm.org/docs/ClangCommandLineReference.html#target-independent-compilation- opcje –

0

gcc cele nie nadążają z platform i architektur, a nie wszystkie z nich obsługuje natywnie PIC jak architektura x86 robi. W niektórych przypadkach tworzenie PIC oznacza dodatkowy narzut, który może być niepożądany, a który chcesz lub potrzebujesz, zależy to od twojego projektu i platformy, na którą celujesz.

0

To zależy od celu. Niektóre cele (takie jak x86_64) są domyślnie niezależne od pozycji, sp -fpic to odbiór i nie ma wpływu na wygenerowany kod. W takich przypadkach można go pominąć i nic się nie zmienia. Inne obiekty docelowe (takie jak 32-bitowe wersje x86) nie są domyślnie niezależne od położenia, więc w przypadku tych maszyn, jeśli pominiesz -fpic dla pliku wykonywalnego, wyłączy on ASLR dla tego pliku obrazu (ale nie dla bibliotek współdzielonych, których używa).

Powiązane problemy