본문 바로가기

소프트웨어/Linux/Device Driver

ARM] ARM 최적화로 인한 코드 오동작 방어

Coretex m3용 firmware를 만들면서 이상한 문제에 봉착했다.

분명 잘 동작하던 코드가 어떠한 코드를 조금만 추가하면 동작하지 않거나, 동작하더라도 이상한 return값을 보내는 경우를 관찰했다.


예를들어..


int fcn()

{

int result = 0;

result = ~~~~; // do anything

return result;

}


위와 같은 코드가 있다고 가정하자. 분명 이 함수를 return 했을때에는 result에 저장된 의도한 값이 return되어야하는데, 실제로 ic에 올려보면 전혀 이상한 값이 return되거나, 값이 없는 경우가 발생하였다.


??


***** 과정보다 결론이 중요하다면 여기 를 클랙해서 먼저 확인!



어디서부터 맥을 짚어가야할지 짐작조차 하지 못했다. 라인 바이 라인으로 삭제하고 디버그해보고 하면서 진행을 해 보았다.

그러던 중 arm asm을 추출해서 확인해 보았더니 정말 이상하게 코드가 생성되었다.


예를들어...

int main(void)

{

...

int ret = fcn();

return 0;

}

위와 같은 코드가 있다면, 정상적으로 빌드된 코드는 fcn함수로 jump하는 asm 코드가 포함되어야 할 것이다.

그런데 문제상황의 바이너리에서 확인을 해 보니, jump 코드가 없고 이상한 store 코드만 달랑 하나 존재했다.


원인은 이러했다.

arm 최적화 O2(혹은 그 이상) 옵션으로인해 자동으로 auto-inline 옵션이 동작되었고, 컴파일러 판단하에 inline 최적화가 가능한 code는 fcn call 대신 부모 함수에 inline 되었다. 여기까지는 별 문제가 없어야 하는데, 문제가 생각 함수에서는 컴파일러가 최적화를 이상하게 수행해버렸다.

현상은 이러했다.

1. inline code가 sotre code 하나밖에 존재하지 않았다.(inline이 정상적으로 처리되지 않았나?)

2. fcn jmp code가 없었다.(inline 처리를 하지 않았다면 jmp라도 존재해야 했을텐데..)


최적화되는 함수를 하나 하나 뜯어보면 왜 이런식으로 최적화가 잘못 되었는지 알 수 있을 테지만(정말..?)

그것은 너무나도 큰 리소스 투입이 예상되기에... 문제가 생길수 있는, 혹은 inline화 되지 말아야 하는 함수에 대해서 보호할 수 있는 처리방법을 찾아보았다.




처리방법 - noinline attribut


ARM에서는 여러가지 __attribute__ 들을 제공한다. 변수의 섹션을 지정하거나 deprecated를 넣어주거나 등등..

그 중 auto-inline을 막아주는 attribute를 함수에 등록할 수 잇다.

사용법은 간단하다. 함수 선언부에 해당 속성을 명시해주면 된다. 예제 코드는 아래와 같다.


int fcn(void) __attribute__((noinline));

...

int fcn(void( { return ~~~;} 


간단히 __attribute__((noinline)); 만 추가해주면 문제 해결이 가능하다.

ref. http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.duibk/CIAGHFBA.html



또한 리눅스에서는 sw최적화 방지를 위해 barrier()라는 방법도 지원한다는데 정확한 확인은 못했다.

키워드는 barrier, rmb, wmb, mb, smp_rmb, smp_wmb, smp_mb, dmb 이므로 궁금하면 찾아보길 바란다.




아 추가적으로 볼 만한 내용이 또 있다.

작성한 코드에서 16bit 자료형으로 선언하고 8bit 형태로 캐스팅해서 부분 부분 접근하는 코드가 많다.

그런데 이런 접근이 최적화에 오류를 발생시킬 수 있다고 한다.

int a;라고 선언해놓고 (shrt)&a +1 과 같이 접근하는 코드들이 c standard에서 지원하지 않는 방법이고, o2이상의 옵션에서 의도치 않은 결과값을 보낼 수도 있다고 한다. 혹 문제가 생긴다면 이런 우너인으로 인한 최적화 오류가 있을지 않을까 하고 생각해 볼 만 하다.(실제 작성된 코드에서는 이렇게 접근하는 코드들이 매우매우 많다)

ref. http://forum.falinux.com/zbxe/index.php?document_srl=&mid=lecture_tip