2016-09-23 17 views
2

이것이 가능하지 않다고 생각했기 때문에 이것을 클릭했다면, 나는 그것에 부딪 칠 때까지 똑같은 생각을했습니다.소스와 컴파일러 플래그가 수정되지 않은 경우에도 오브젝트 파일의 컴파일이 달라질 수 있습니까?

저는 PIC 용 C로 작성된 프로젝트에서 작업 중이며, Makefile로 빌드되었습니다. Makefile은 매우 혼란스러워서 정리하고 싶었습니다. (이 프로젝트에 하위 디렉토리 SDCC와 GPUTILS와 내장..)

make clean 
make 
md5sum ./* > ../allsums.txt 

다음 : 나는 그것을 한 동안 아무것도 휴식하지 않았다 확인하기 위해, 나는 신선한 메이크업 다음 모든 파일의 해시를 기록 나는 Makefile을 수정하고 이번에는 결과 파일을 allsums.txt과 비교했다. 흥미롭게도 .o 파일의 해시는 일치하지 않지만 최종 결과는 일치했습니다. 그 문제가 내가 어떻게 든 창조 한 문제라고 가정하면, 나는 그것을 사냥하려고 많은 시간을 보냈다.

그런 직감에, 나는 원래 Makefile을 사용하여 이런 짓을 :

make clean 
make 
md5sum ./* > ../allsums.txt 
make clean 
make 
md5sum -c ../allsums.txt 

나는 오브젝트 파일도 여기에 변경된 것을 발견! 어떤 검색은 this question으로 이어 졌는데, 이는 (적어도 gcc의 경우) .o 파일이 각 컴파일 사이에서 변경되었음을 확인했습니다.

이 원인은 무엇입니까?

+0

아니요, gcc는 빌드가 변경되지 않는 한 동일한 파일 (즉, 일치)을 생성합니다. 소스 파일에 컴파일 인자'-DDATE = "\'date \'"'가있는 곳 ('char build_time [] = DATE')과 같은 것이 있으면 그것들이 바뀔 수 있습니다. –

+0

이것을 이해/해결하는 더 좋은 방법은 각 파일의 16 진 덤프 ('od' 또는'xxd')와'diff'를 사용하여 어떤 부분이 변경되는지 확인하는 것입니다. 그런 다음 주어진'.o' 섹션에서 어떤 오프셋이 변경되었는지를보기 위해 거꾸로 작업 할 수 있습니다. 그런 다음 특정 기호와 연결하십시오. 그런 다음'.h' 또는'.c' 파일에서 심볼의 정의를 찾으십시오. 또한, 길이가 동일합니까? –

+0

개체 및 실행 파일에 빌드 별 정보가 포함되는 경우는 흔합니다. 예를 들어, PE 헤더에는 링커에서 채워지는 타임 스탬프 필드가 들어 있습니다 (PE는 Windows에서 실행 파일 및 DLL 형식 임). –

답변

3

개체의 디버깅 정보 (기호, 날짜)는 코드가 완전히 동일하더라도 개체를 변경할 수 있습니다.

단지 개체를 제거, 당신이 어떤 변화를하지 않도록하려면/객체를 비교 제거 객체에 그들에 체크섬을 수행

strip *.o 

가장 좋은 방법은, 그렇지 않으면 당신은 확신 할 수 없다.

주 (동일한 기술은 실행 파일에 적용 할 수 있습니다) : 당신은 당신이 그들을 연결할 수 있지만 디버깅하는 힘든 시간을해야합니다 개체를 제거하면. 당신은 (다음, theobject.o이 변경되지 않습니다) 사본에 그것을 할 수 있습니다 : 배달하기 전에 우리의 실행 파일의 "공식 생산"을 수행 할 때

strip theobject.o -o theobject_stripped.o 

우리는 그 과정을 사용합니다.

사실 우리는 다른 방법으로 라운드를합니다. 우리는 제거 된 실행 파일을 비교합니다. 차이가 있다면, 제거 된 개체를 비교하여 범인을 찾아 범위를 좁 힙니다. 그런 다음 소스의 버전 제어 시스템을 사용하여 변경된 이유를 찾습니다.

: 사용자 지정 시간 종속 매크로를 사용하여 개체 파일 (-DDATE=\"somedate\")의 날짜를 정의하는 경우 체크섬 프로세스에 스트립 작업 이상이 필요할 것입니다. 오브젝트 파일 (또는 파일)에서 역순으로 작업 (날짜/버전/삭제)은 사용자 정의 도구를 사용하여 수행해야합니다. 내 보낸 심볼의 버전 (Version.o)을 포함하는 파일 하나에서만 매크로를 적용하여이 기능을 활용하고 대부분의 오브젝트 파일을 그대로 사용할 수 있습니다.해당 파일에

체크섬이 다를 수 있지만, 다른 사람이 동일합니다 (또는 coleagues가 무의미하게 당신을 위해 매우 열심히하고 있습니다)

는 편집 : 비슷한 도구는 sdobjcopy의 인터페이스라는 SDCC 당신이 한 이는 매우 매우 objcopy 모양 및 제거하는 기능

sdobjcopy --strip-all theobject.o theobject_stripped.o 

객체가합니다 ( --strip-all 옵션이 너무 "폭력"의 경우도 --strip-debug 옵션이있다)을

,536 자세한 내용은

체크 sdobjcopy man page을 참조하십시오.

+0

차이점이있을 확률이 높은 이유를 확인했지만 오브젝트 파일을 제거하는 것은 다양한 부분이 실제 프로그램 데이터에있을 수 있으므로이를 정리하는 것이 확실하지 않습니다. 예를 들어 빌드 타임 스탬프가 포함 된 시작 배너 또는 내부 버전 문자열이있을 수 있습니다. –

+0

@ JohnBollinger : 맞습니다. 그렇다면 사용자 정의 도구로 되돌릴 수있는 사용자 정의 프로세스입니다. 예를 들어 strip + 버전/날짜 영역을 찾아서 비워 둘 수 있습니다. 이 사용자 정의 프로세스는 makefile에서 쉽게 식별 할 수 있어야합니다. –

+2

검색 할 주요 단계는 '재현 가능 빌드'입니다. 보안 앵글에서 가져 오는 것이지만 문제는 동일합니다. –