Stworzyłem dwa programy w C.
Program 1
int main() { }
Program 2
int main() { //Some Harmless comments }
AFAIK, podczas kompilacji kompilator (gcc) powinien ignorować komentarze i zbędne białe znaki, a zatem dane wyjściowe muszą być podobne.
Ale kiedy sprawdziłem sumy md5 wyjściowych plików binarnych, nie pasują. Próbowałem też kompilować z optymalizacją -O3
i-Ofast
jednak wciąż nie pasuje.
Co tu się dzieje?
EDYCJA: dokładne polecenia i sumy md5 to (t1.c to program 1, a t2.c to program 2)
gcc ./t1.c -o aaa
gcc ./t2.c -o bbb
98c1a86e593fd0181383662e68bac22f aaa
c10293cbe6031b13dc6244d01b4d2793 bbb
gcc ./t2.c -Ofast -o bbb
gcc ./t1.c -Ofast -o aaa
2f65a6d5bc9bf1351bdd6919a766fa10 aaa
c0bee139c47183ce62e10c3dbc13c614 bbb
gcc ./t1.c -O3 -o aaa
gcc ./t2.c -O3 -o bbb
564a39d982710b0070bb9349bfc0e2cd aaa
ad89b15e73b26e32026fd0f1dc152cd2 bbb
I tak, sumy md5 pasują do wielu kompilacji z tymi samymi flagami.
Swoją drogą mój system to gcc (GCC) 5.2.0
iLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux
c
gcc
optimization
binary-reproducibility
zarejestrowany użytkownik
źródło
źródło
Odpowiedzi:
Dzieje się tak, ponieważ nazwy plików są różne (chociaż dane wyjściowe są takie same). Jeśli spróbujesz zmodyfikować sam plik (zamiast mieć dwa pliki), zauważysz, że wyjściowe pliki binarne nie są już różne. Jak ja i Jens powiedzieliśmy, dzieje się tak dlatego, że GCC zrzuca cały ładunek metadanych do tworzonych plików binarnych, w tym dokładną nazwę pliku źródłowego dzieje się tak tworzonych (i AFAICS tak robi).
Spróbuj tego:
To wyjaśnia, dlaczego sumy md5 nie zmieniają się między kompilacjami, ale są różne w różnych plikach. Jeśli chcesz, możesz zrobić to, co zasugerował Jens i porównać wynik
strings
każdego pliku binarnego, a zauważysz, że nazwy plików są osadzone w pliku binarnym. Jeśli chcesz to „naprawić”, możeszstrip
usunąć pliki binarne i metadane:źródło
Najczęstszym powodem są nazwy plików i znaczniki czasu dodane przez kompilator (zwykle w części informacji o debugowaniu sekcji ELF).
Spróbuj biegać
i możesz zobaczyć powód. Kiedyś użyłem tego, aby dowiedzieć się, dlaczego to samo źródło powodowałoby inny kod, gdy był kompilowany w różnych katalogach. Okazało się, że
__FILE__
makro rozwinęło się do bezwzględnej nazwy pliku, różnej w obu drzewach.źródło
Uwaga : pamiętaj, że nazwa pliku źródłowego trafia do pliku binarnego bez ściągnięcia, więc dwa programy pochodzące z plików źródłowych o różnych nazwach będą miały różne skróty.
W podobnych sytuacjach, jeśli powyższe nie ma zastosowania , możesz spróbować:
strip
przeciwko układowi podwójnemu, aby usunąć trochę tłuszczu. Jeśli usunięte pliki binarne są takie same, to niektóre metadane nie są niezbędne do działania programu.strings
lub zrzuć oba programy do szesnastkowego i uruchom różnicę na dwóch zrzutach szesnastkowych. Po zlokalizowaniu różnic, możesz spróbować sprawdzić, czy jest jakiś rym lub powód (PID, znaczniki czasu, znacznik czasu pliku źródłowego ...). Na przykład możesz mieć procedurę przechowywania sygnatury czasowej w czasie kompilacji do celów diagnostycznych.źródło
gcc (GCC) 5.2.0
iLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux