2011-02-25 4 views
9

소스 코드를 Linux를 실행하는 ARM 플랫폼으로 이식해야합니다. 불행히도 정렬되지 않은 메모리 액세스 문제가 발생했습니다. 소스는 포인터 캐스트와 액세스를 많이 사용합니다.ARM 정렬되지 않은 메모리 액세스 해결 방법

아래 코드는 바이러스와 같은 코드베이스에 퍼져 있습니다. gcc -Wcast-align 명령 줄 옵션 덕분에 문제가있는 위치를 찾아 낼 수 있지만 수천 개가 넘는 인스턴스가 있습니다. echo 2 > /proc/cpu/alignment에 사용

u = (IEC_BOOL); 
(((*(IEC_LINT*)pSP).H < b.H) 
    || (((*(IEC_LINT*)pSP).H == b.H) && ((*(IEC_LINT*)pSP).L < b.L))) ? 1 : 0); 
*(IEC_DWORD OS_SPTR *)pSP = 
    (IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP >> u); 
*(IEC_DWORD OS_SPTR *)pSP = 
    (IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP << -u); 
u = (IEC_BYTE)((*(IEC_DINT*)pSP != b) ? 1 : 0); 
*(IEC_DWORD*)pSP = (IEC_DWORD)(*(IEC_DWORD*)pSP & w); 
(*(IEC_ULINT*)pSP).H += u.H; 
(((*(IEC_ULINT OS_SPTR *)pSP).H == b.H) 
    && ((*(IEC_ULINT OS_SPTR *)pSP).L > b.L))) ? 1 : 0); 
u = (IEC_BYTE)((*(IEC_REAL*)pSP >= b) ? 1 : 0); 

는 리눅스 커널이 문제를 해결하지만, 응용 프로그램의 성능이 더 이상 허용되지 않는 지점으로 저하한다.

GCC (v4.4.1) 컴파일러에 대해 __unaligned 또는 __packed 키워드를 검색했지만 아직 비어 있습니다.

많은 Poblematic 코드 라인이 다소 복잡한 정규 표현식/대체 코드로 고정 될 수 있다고 생각했지만 지금은 그렇게하고 난 후에도이 접근법은 엄청난 양의 지루한 작업을 수행하게됩니다.

이 작업을 수행하는 방법에 대한 제안 사항이 있으십니까? gcc 4.5 컴파일러 플러그인은 과도하다고 생각하지만 정규 표현식보다 나은 점이 있습니까? 어떤 다른 제안을 할 수 있습니까? 몇 가지 드문 경우 커널에 의존 할 수 있기 때문에 반드시 모든 문제 인스턴스를 수정해야하는 것은 아닙니다.

+11

나는 이것을 TheDailyWTF.com으로 옮겨야한다는 농담을하고 싶다. – Crashworks

+2

현대 언어학에 대한 우리의 연구를 계속하면서, 우리는 임베디드 프로그래머가 일반적으로 사용하는 C 언어의 표본을 가지고 있습니다. 대략 영어로 번역 된 위의 텍스트는 "F *** YOU!"를 의미합니다. 자연 언어는 아무리 위선적 인 것에도 불구하고 양심적 인 가치를 전달할 수는 없지만 여기에 전달 된 독자의 인성에 대해서는 무시합니다. – Dmitri

답변

7

어떤 경우에는 도움이 될 수있는 __attribute__((__packed__))이 있지만 실제로이 코드는 한 번만 해결할 때보 다 문제를 해결하는 데 더 많은 시간을 할애하기 때문에 나중에보다는 빨리 정리해야한다고 생각합니다. 그리고 모두를 위해서.

+1

나는 이것이 가능한 해결책이라고 생각하지만, 먼저 코드를 작성한 사람은 해고되어야한다. 그건 그렇고 코드는 아마도 깨진 경우 모든 포인터에서'-fno-strict-aliasing' 또는'__attribute __ ((may_alias))'를 필요로 할 것입니다. –

+0

기본적으로 다음과 같은 이유로 IEC_DWORD *는 도움이되지 않습니다. typedef uint32_t, POD 유형 포인터가 이것에 캐스트되는 순간에는 4 바이트 정렬로 추정됩니다. 코드가 깨졌을 때, 작동하는 타겟을위한 에뮬레이터를 작성하려고합니다 : –

+0

'__attribute __ ((__ packed __))'는 이미 구조체 멤버에 사용되었지만 코드가 구조체 대신 POD 유형으로 변환되기 때문에 이것은 쓸모가 없다. 하지만이 프로그램을 사용할 수 있는지 테스트 프로그램을 통해 시험해 보겠습니다. – trenki

0

이 문제는 ARM이 32 비트 시스템이고 Linux 상자가 64 비트 모드에서 실행된다고 가정 할 수 있습니다. 또는 코드가 16 비트 시스템에서 실행 중이라고 가정 할 수도 있습니다.

한 가지 방법은 액세스되는 기본 구조를 보는 것입니다. "H"및 "L"멤버는 64 비트 인 것처럼 액세스되는 32 비트 유형이 될 수 있습니다.

L 및 H의 유형을 수정하여 코드의 작동을 개선하십시오.

은 (코드 조각이 나 기본 구조, 응용 프로그램의 세부 사항을 공개하지 않는 한 인정 하듯이,이, 허공에 자상입니다.)

2

와우, 신성 엉망입니다. 컴파일러를 만지면 어디서나 얻을 수 없습니다. 이 코드는 모든 아키텍처에서 불법이지만 일부 (예 : x86)에서 작동합니다. 나는 코드 자체를 고칠 것이다.

슬프게도 그럴 수있는 방법이 없습니다. 그러나 검색 및 교체 목록이 길면 길어질 수 있으며 나머지는 수동으로 수정해야합니다. 이러한 데이터 유형의 선언을 제거하여 시작 했으므로 놓친 코드를 컴파일하면 오류가 발생합니다. 그런 다음 "* (IEC_DWORD OS_SPTR *) pSP =" with "set_dword (pSP," "과 같은 검색 및 교체 스 니펫. 인라인 함수"set_dword "를 사용하여 올바른 작업 수행. 당신이 상상할 수있는대로 쉽게 바꿀 수 있습니다. 여전히 많은 양의 수작업으로 해결할 수 있습니다.

내가 생각할 수있는 유일한 방법은 컴파일러 플러그인 일 것이고 모든 포인터를 전체 편집 단위에는 정렬 1이 있습니다.그러면 컴파일러는 모든 것을 바이트로드/저장합니다. 아마 당신이 의도 한 코드 그 이상을 위해 그것을 끝낼 것입니다. 이것은 아마 소리처럼 달성하기 쉽지 않습니다.

관련 문제