소중한 삽질2009/05/21 01:21
오래간만에 다시 키보드에 손을 올려놓게 되었네요.
(사실 하루 24시간 중 자고 밥먹는 8시간 정도를 제외하면, 나머지 시간은 키보드에서 손이 떨어지질 않습니다. :) )

요즘 주로 맡고 있는 업무가 임베디드 리눅스와 관련되다보니, 이번에는 그와 관련된 내용을 한번 작성해보겠습니다.
제가 리눅스 분야, 특히 임베디드 리눅스은 아직 몇 년되지 않았기 때문에,
혹시 틀린 내용이나 부연 설명이 필요한 부분은 주저말고 지적 부탁드립니다.

일반적인 리눅스 환경과 달리 임베디드에서는 이전 프로그래밍시절 이슈가 여전히 존재합니다. 

바로 실행파일의 크기 문제죠.

저희 선배 프로그래머들은 프로그램의 속도도 빠르고, 메모리도 적게 사용하고, 바이너리의 크기도 작은 
그러한 이상적인 모델을 꿈꿔왔고, 실제로도 그래야지만 제품이 생산될 수 있었습니다.
(호랑이 담배피던 시절 같은 이야기를 몇살 위인 형들에게 들을수 있을 만큼 그리 오래되지는 않았습니다. ^^)

반면에 요즘은 학교 숙제로 구구단 출력 프로그램 같은 작은 프로그램을 작성하면서도,
실행바이너리보다도 몇 백 배나 큰 JVM에서 Java 코드를 수행하곤 합니다.

즉 요즘 PC환경에서는 속도가 이슈지 
메모리 사용이나, 바이너리의 크기가 문제가 되는 시대는 아닙니다.


하지만 임베디드 환경에서는 또 다른 세상입니다.
여전히 PC와 비교하여 상대적으로 CPU는 느리고, 메모리도 작고, Flash도 작습니다.



그래서 실제 개발시에도 ELF(Executable and Linking Format) 바이너리의 크기를 줄이기 위하여 strip을 하게 됩니다. 
strip 명령어를 수행하게 되면 바이너리 파일의 Header 정보와 심볼 정보들이 모두 삭제되기 때문에 
파일의 물리적인 크기 또한 상당히 줄어들게 됩니다.

실제 이렇게 줄어든 바이너리의 크기는 그렇지 않은 것에 비하여 2~3배 정도 차이가 나게 됩니다
아래의 예제는 이번 테스트에서 이용한 실행 파일의 크기를 비교한 것입니다.


문제는 이렇게 strip한 바이너리를 수행하다가 예기치 않은 오류로 core 파일만을 남겨두고 장렬히 전사(?)한 경우에도,
gdb로 core와 바이너리를 가지고 back trace해보면, Symbol('??'로 표시됨)이 다 생략되어서 나오게 됩니다.


개발자 입장에서 문제는 있다고 하는데, 어떤 부분이 문제가 되고 있는지 gdb가 알려주지 않기 때문에 참 난감한 상황입니다. 이에 대한 해결방법으로 ‘strip으로 symbol이 없는 바이너리'가 생성한 core 파일과 ‘symbol을 모두 가지고 있는 바이너리’ – (이하 ‘symbol 바이너리라고 하겠습니다.)를 이용하여 gdb load하는 방법이 있습니다.


gdb에 실행 바이너리와 core 파일을 load, core 파일은 최적화된 바이너리생성된 것을, 실행 바이너리는 최적화된 바이너리대신에 ‘symbol 바이너리 load합니다. 이런 경우 아래의 그림에서 확인할 수 있듯이, back trace도 가능하고, 각 변수의 값과 code도 확인이 가능합니다


이때 주의할 내용으로 두 바이너리의 최적화 옵션은 동일해야 합니다
예를 들어, ‘strip된 바이너리에서 ‘-O2’를 사용하는 경우, ‘symbol 바이너리에서도 이 옵셥을 build시 사용해야 합니다


[Postscript]

Network이 연결되는 환경이라면 NFS로 타겟의 mount point를 host PC로 만드는 것도 좋은 방법입니다.
대신 저는 그렇게 작업을 하면 Target에서 직접 실행하는 것보다 꽤 실행 속도가 저하되는 것을 느꼈습니다.

Posted by again4you