2013-08-20 2 views
0

저는 이상한 문제에 봉착했습니다. this과 다소 비슷합니다. Windows Phone 8 기본 DLL 프로젝트 (대부분 C++이지만 ARM 어셈블리 소스가 포함되어 있음)가 있습니다. 소스가 ARM 모드 (즉, Thumb이 아님)입니다. C++가 Thumb으로 컴파일됩니다.WinPhone8에서 ARM (엄지 손가락 제외)이 지원됩니까?

C++이 어셈블리 루틴을 호출하려고하면 응용 프로그램이 충돌합니다. 디스 어셈블리의 call 명령은 즉각적인 오프셋을 갖는 BLX입니다. 모드를 무조건 ARM으로 다시 전환해야합니다. 그러나 어떻게 든 그럴 수는 없습니다.

예외에 대한 세부 정보가 있습니다. 예외 코드는 0xc000001d (잘못된 연산)이며 충돌 컨텍스트 구조체에있는 PC의 값은 0x696d5985입니다. 어느 모드에서도 불가능합니다. 비트가 맞지 않습니다. 비트 0은 하나입니다. BLX 명령어는 1b f0 0c eb이됩니다. 해독하면 2 부분으로 구성된 Thumb 스타일 BLX이되며 4 개의 위치가 조정됩니다. 충돌 컨텍스트의 T 플래그는 SET (CPSR = 0x60000010)입니다.

기기가 없지만 베타 테스터의 오류 로그는 매우 결정적입니다. 어셈블리 호출하기 바로 전에 디버그 로그 레코드가 있습니다. 그 다음에 충돌.

편집 : related. 그러나 그들은 어셈블러 자체 (armasm)가 ARM을 Thumb으로 변환한다고 주장합니다. 저에게 있어서는 그렇지 않습니다. 적어도 정적이지는 않습니다. DLL에는 어셈블리 소스 (CODE32)에 지정된대로 올바른 ARM 코드가 포함되어 있습니다.

편집 : 약간 다른 점프의 순서로 시도 :

ldr r12, target 
and r12, r12, #0xfffffffe ; To be sure 
bx r12 ;BX to a register with a cleared 0th bit. Doesn't get any more explicit than that. 

같은 결과. 마치 상점에서 어딘가에서 일어나는 이상한 코드 모핑이 있거나 OS 자체가 모드 스위치를 잡아서 막는 것처럼 보입니다.

코드 변형은 나머지 충돌 데이터와 함께 실행 파일의 일부를 충돌 로그에 덤프하여 감지 할 수 있습니다. 하지만 전체 코드베이스를 Thumb으로 변환하지 않으면 OS 간섭으로 무엇을 할 수 있습니까? 그것은 단지 다시 컴파일하지 않습니다. dwelch에 대한

편집 : 컴파일 된 C 코드에서 호출 순서는 다음과 같이 진행됩니다

.text:1000A35E     MOV    R2, #g_Host ;Three parameters 
.text:1000A366     MOV    R1, R5 
.text:1000A368     MOV    R0, R6 
.text:1000A36A     BLX    Func ; Code bytes 1B F0 0C EB 

BLX 즉시 주소로 모드를 전환 할 수 있습니다. 조건부가 아니며 bx register과 같습니다. 호출 대상은 썽크입니다 :

.text:10025984     B    Func_Impl 

그리고 충돌 주소는 썽크 플러스 하나입니다 : 5985.

이 컴파일 된 DLL의 분해,하지만 난이 정확히 무엇을 실행하는 것입니다된다는 보장이 없다 장치에. 연결된 MSDN 스레드의 사용자는 디버거의 해체도 을보고 ARM이 수행해야하는 Thumb을 확인했습니다. Microsoft, IIRC, 게시자에서 장치로 경로에있는 응용 프로그램 코드 수정에 대한 특허 보유 그 이유가 될 수 있습니다.

+0

라이브러리 및 응용 프로그램을 빌드 할 때 필요한 모든 인터 워킹 플래그를 활성화 했습니까? –

+0

없습니다. 그리고 BLX 명령은 툴체인이 무슨 일이 벌어지고 있는지 알고 있습니다. –

+0

hmmmmm .... 우리가 모르는 뭔가가 있어야합니다. Thumb 명령어는 매우 제한적 이었지만 Thumb2는 ARM 모드보다 훨씬 효율적인 다른 동물입니다. ARM 모드를 덤프하고 Thumb2 모드로 코딩 할 때가 된 것 같습니다. –

답변

2

나는 이것에 대한 직접적인 지식이있다; 저는 Windows RT의 커널에서 원인을 알아 낸 리버스 엔지니어였습니다. 특히 Windows NT 커널 (ntoskrnl.exe)의 KeContextFromKframes은 작업 스위치에 대한 스레드의 상태를 고정 할 때 T 비트를 설정합니다. 즉, 인터럽트 이후 다시 시작하면 충돌이 발생합니다.

Microsoft의 PatchGuard를 깨지 않고 Chrome의 JITter를 직접 포팅 할 수 없기 때문에 RT/WinPhone의 탈옥수가되었습니다. 커널 드라이버를로드하여 KeContextFromKframes을 패치 할 수 있지만 나중에 PatchGuard가 충돌을 일으킬 수 있습니다.

0

엄지에서 팔까지 BLX를 사용할 때 정렬되지 않은 암장 주소를 가져올 수 없습니다. 하위 2 비트는 두 번째 명령에 의해 수행됩니다. 팔 문서를 읽고, 당신은 기본적으로 첫 번째는이 개 지침이 : PC가 주소 LR의 수정에

0xF01B 

if H == 10 then 
LR = PC + (SignExtend(offset_11) << 12) 

기본적으로 첫 번째 명령의 결과를 경우이 명령 플러스 4 (이 개 지침에 앞서).

LR = PC + 0x1B000 

두 번째는

0xEB0C 

if H == 01 then 
PC = (LR + (offset_11 << 1)) AND 0xFFFFFFFC 
LR = (address of next instruction) | 1 
CPSR T bit = 0 

최종 결과는

PC = (address of next instruction + 0x1B000 + 0x318) AND 0xFFFFFFFC 
PC = (address of next instruction + 0x1B318) AND 0xFFFFFFFC 
LR = address of next instruction | 1 
CPSR T bit = 0, arm mode. 

나는 당신의 충돌이 다른 곳이라고 생각합니다.

해당 코드의 디스 어셈블리, 지침 등을 게시해야합니다. 1110와 AND 연산에 의해

까지 당신의 BX의 시도로, 당신은 미끄러운 경사를 걷고있다 ...

ARM/Thumb state transfers 
If Rm[1:0] == 0b10, the result is UNPREDICTABLE, as branches to non word-aligned 
addresses are impossible in ARM state. 

당신은 lsbit을 삭제뿐만 아니라 잠재적으로 정렬되지 않은 주소를 허용하고 있습니다. r12에서 대상 주소를 제대로 계산하지 못했고 팔 코드가 아닌 경우 제대로 작동하지 않습니다. 진행 상황을 명확히 보여줄뿐만 아니라 목적지 주소의 첫 번째 지시 사항이나 몇 가지 사항을 게시하십시오.

예외 코드가 엄지 주소에서 엄지 손가락 모드임을 알리는 것처럼 보입니다. 해당 주소/부근의 코드에 대한 디스 어셈블리를 게시하십시오.

2

Windows Phone 8의 인터럽트 처리기가 Thumb 플래그를 복원하지 않고 대신 1로 하드 코드하는 Michael Schnell suggested elsewhere 신사. 테스트를 통해 이론을 확인할 수 있습니다. 다음 코드 :

THUMB 
ASMTest 
    mov r12, lr 
    blx a 
    mov lr, r12 
    bx lr 

    ALIGN 4 
    ARM 
a 
    bx lr 

가 지속적으로 디버거에서 충돌하지만, 예상대로 실행될 때 debuggerless (즉 어떤 인터럽트 ARM 모드에서..). ARM 모드에서 0x10000 반복의 빈 루프를 삽입하면 몇 가지 시도가 실행되고 충돌이 발생합니다.

관련 문제