9

Nauczyłem się od this recent answer, że gcc i clang zawierają nazwę pliku źródłowego gdzieś w binariach jako metadane, nawet jeśli debugowanie nie jest włączone.Dlaczego typowe kompilatory języka C zawierają nazwę pliku źródłowego na wyjściu?

Nie mogę naprawdę zrozumieć, dlaczego to powinien być dobry pomysł. Oprócz niewielkiego ryzyka związanego z prywatnością, dzieje się tak również wtedy, gdy optymalizuje się rozmiar pliku binarnego (-Os), który wygląda na nieefektywny.

Dlaczego kompilatory zawierają te informacje?

+2

To nie tylko GCC, Clang to robi (i każdy kompilator, który tworzy pliki binarne ELF zgodne z [specyfikacją] (http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf)). – cyphar

+1

@cyphar Przyznaję, że po prostu wpadłem na to zamiast czytać wszystkie 60 stron, ale znalazłem PLIK wspomniany tylko na stronie 25 tego dokumentu i nie mówi on, że jest to obowiązkowe ("Konwencjonalnie, nazwa symbolu podaje nazwę plik źródłowy powiązany z plikiem obiektowym "). –

+0

Nie przeczytałem również wszystkich 60 stron. Ale jeśli chodzi o standardy "konwencjonalnie" oznacza "prawdopodobnie powinieneś to zrobić, ponieważ ludzie mogą na nim polegać". Na koniec dnia, jeśli dostaniesz specyfikację, łatwiej po prostu podążaj za nią (z uwagi na to, że Twoi użytkownicy mogą zdecydować się na użycie najbardziej ezoterycznych funkcji wyrażonych w standardzie) niż próbować i wyplątać się z wyjścia wdrażanie rzeczy, których nie musisz. w końcu GNU jest krainą ekstremalnych ilości dodatkowych funkcji. – cyphar

Odpowiedz

6

Powód, dla którego GCC zawiera nazwę pliku, służy głównie do celów debugowania, ponieważ pozwala programistce zidentyfikować, z którego pliku źródłowego dany symbol pochodzi z (zwięźle) przedstawionego w ELF spec p1-17 i dalej rozwinięty w some Oracle docs on linking.

Przykład użycia sekcji STT_FILE jest podany przez this SO question.

nadal jestem zdezorientowany, dlaczego zarówno GCC i Clang nadal zawierają go nawet jeśli podasz -g0, ale można zatrzymać go przed tym STT_FILE z -s. Nie mogłem znaleźć żadnego wyjaśnienia tego, ani nie mogłem znaleźć "oficjalnego powodu" dlaczego STT_FILE jest zawarty w specyfikacji ELF (który jest bardzo lakierem).

5

nauczyłem się od tej ostatniej odpowiedzi, że gcc zawiera nazwę pliku źródłowego gdzieś w binarnym jako metadane, nawet podczas debugowania nie jest włączony.

Nie całkiem. W nowoczesnym obiekcie ELF plików nazwę pliku rzeczywiście jest symbolem typu FILE:

$ readelf bignum.o # Source bignum.c 
[...] 
Symbol table (.symtab) contains 36 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 FILE LOCAL DEFAULT ABS bignum.c 
    2: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    3: 0000000000000000  0 SECTION LOCAL DEFAULT 3 
    4: 0000000000000000  0 SECTION LOCAL DEFAULT 4 
    5: 0000000000000000  0 SECTION LOCAL DEFAULT 5 
    6: 0000000000000000  0 SECTION LOCAL DEFAULT 6 
    7: 0000000000000000  0 SECTION LOCAL DEFAULT 7 
    8: 0000000000000000  0 SECTION LOCAL DEFAULT 8 
    9: 00000000000003f0 172 FUNC GLOBAL DEFAULT 1 add 
    10: 00000000000004a0 104 FUNC GLOBAL DEFAULT 1 copy 

Jednak, gdy pozbawiono, symbol znika:

$ strip bignum.o 
$ readelf -all bignum.o | grep bignum.c 
$ 

Tak, aby zachować prywatność, rozebrać wykonywalny, lub skompiluj/połącz z -s.

+1

Dlaczego "niezupełnie"?Nadal uważam to za "zawarte w pliku binarnym", chociaż prawidłowo wskazuje się, że jest osadzony w sposób, który ułatwia jego usunięcie. Moje pytanie dotyczyło motywacji. –

+1

@FedericoPoloni Tylko bardzo subtelny powód "niezupełnie": czy meta dane tabeli symboli? Jest * wymagane * dla udanego połączenia. Jednak dane debugowania nie mają własnej sekcji ELF i można je usunąć. To naprawdę nie jest duży problem i nie powinno przeszkadzać w zrozumieniu. – Jens

+1

Chociaż tablica symboli jest ogólnie potrzebna do łączenia, ten konkretny symbol nie jest. Więc zasadniczo używa tabeli symboli jako miejsca przechowywania niektórych metadanych. – Barmar