Programming

주석 만있는 두 바이너리 프로그램이 gcc에서 정확히 일치하지 않는 이유는 무엇입니까?

procodes 2020. 8. 3. 20:39
반응형

주석 만있는 두 바이너리 프로그램이 gcc에서 정확히 일치하지 않는 이유는 무엇입니까?


두 개의 C 프로그램을 만들었습니다

  1. 프로그램 1

    int main()
    {
    }
    
  2. 프로그램 2

    int main()
    {
    //Some Harmless comments
    }
    

AFAIK는 컴파일 할 때 컴파일러 (gcc)가 주석과 중복 공백을 무시해야하므로 출력이 비슷해야합니다.

그러나 출력 바이너리의 md5sum을 확인하면 일치하지 않습니다. 또한 최적화 컴파일 시도 -O3하고 -Ofast있지만 아직 일치하지 않습니다.

여기서 무슨 일이 일어나고 있습니까?

편집 : 정확한 명령과 md5sum이 있습니다 (t1.c는 프로그램 1이고 t2.c는 프로그램 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

그렇습니다. md5sum은 동일한 플래그로 여러 컴파일에서 일치합니다.

BTW 내 시스템이 gcc (GCC) 5.2.0Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux


문자열 이름이 같더라도 파일 이름이 다르기 때문입니다. 두 개의 파일이 아닌 파일 자체를 수정하려고하면 출력 바이너리가 더 이상 다르지 않습니다. Jens와 내가 말했듯이 GCC 는 정확한 소스 파일 이름 (및 AFAICS도 clang도 포함)을 포함하여 빌드하는 바이너리에 전체 메타 데이터를 덤프하기 때문 입니다.

이 시도:

$ cp code.c code2.c subdir/code.c
$ gcc code.c -o a
$ gcc code2.c -o b
$ gcc subdir/code.c -o a2
$ diff a b
Binary files a and b differ
$ diff a2 b
Binary files a2 and b differ
$ diff -s a a2
Files a and a2 are identical

이것은 md5sum이 빌드간에 변경되지 않는 이유를 설명하지만 파일마다 다릅니다. 원하는 경우 Jens가 제안한 작업을 수행하고 strings각 바이너리 의 출력을 비교 하여 파일 이름이 바이너리에 포함되어 있음을 알 수 있습니다. 이 문제를 "수정" strip하려면 바이너리를 사용하면 메타 데이터가 제거됩니다.

$ strip a a2 b
$ diff -s a b
Files a and b are identical
$ diff -s a2 b
Files a2 and b are identical
$ diff -s a a2
Files a and a2 are identical

The most common reason are file names and time stamps added by the compiler (usually in the debug info part of the ELF sections).

Try running

 $ strings -a program > x
 ...recompile program...
 $ strings -a program > y
 $ diff x y

and you might see the reason. I once used this to find why the same source would cause different code when compiled in different directories. The finding was that the __FILE__ macro expanded to an absolute file name, different in both trees.


Note: remember that the source file name goes into the unstripped binary, so two programs coming from differently named source files will have different hashes.

In similar situations, should the above not apply, you can try:

  • running strip against the binary to remove some fat. If the stripped binaries are the same then it was some metadata that isn't essential to the program operation.
  • generating an assembly intermediate output to verify that the difference is not in the actual CPU instructions (or, however, to better pinpoint where the difference actually is)
  • use strings, or dump both programs to hex and run a diff on the two hex dumps. Once located the difference(s), you might try and see whether there's some rhyme or reason to them (PID, timestamps, source file timestamp...). For example you might have a routine storing the timestamp at compile time for diagnostic purposes.

참고URL : https://stackoverflow.com/questions/32400931/why-dont-two-binaries-of-programs-with-only-comments-changed-exactly-match-in-g

반응형