2013-08-20 2 views
0

Я столкнулся с странной проблемой, несколько похожей на this. У меня есть собственный DLL-проект Windows Phone 8, в основном C++, но с источником сборки ARM. Источник находится в режиме ARM (то есть не Thumb). C++ скомпилирован в Thumb.Совместим с ARM (не Thumb) на WinPhone8?

Приложение аварийно завершает работу, когда C++ пытается вызвать процедуру сборки. Команда вызова при разборке представляет собой BLX с немедленным смещением - он должен переключать режим обратно на ARM, безоговорочно, но каким-то образом это не так.

У меня есть детали исключения. Код исключения - 0xc000001d (недопустимая операция), а значение ПК в структуре контекста crash равно 0x696d5985. Это невозможно в любом режиме - он смещен, бит равен нулю. Инструкция BLX идет 1b f0 0c eb - если вы расшифровываете, это двухкомпонентный BLX-стиль в полном порядке, с 4-выровненным смещением. Флаг T в контексте сбоя - SET (CPSR = 0x60000010).

У меня нет устройства, но журнал сбоев из бета-тестера довольно убедительный. У меня есть запись журнала отладки прямо перед вызовом в сборку. Затем крушение.

EDIT: related. Они утверждают, однако, что сам ассемблер (armasm) переводит ARM в Thumb. Это не относится ко мне - по крайней мере, не статически. DLL содержит соответствующий код ARM, как указано в источнике сборки (CODE32).

EDIT: попробовал с несколько иной последовательности прыжков:

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. 

Тот же результат. Похоже, есть какой-то странный код, который происходит где-то в Магазине, или сама ОС ловит переключатели режимов и предотвращает их.

Модификацию кода можно, вероятно, обнаружить, сбросив части исполняемого файла в журнал сбоев вместе с остальными данными об аварии. Но что я могу сделать с помехами ОС, не доходя до полной кодовой базы до Thumb? Он не просто перекомпилирует.

EDIT для 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 утверждал, что они посмотрели на дизассемблирование в отладчике и увидели Thumb, где должна была быть ARM. Microsoft, IIRC, имеет патент на изменение кода приложения на пути от издателя до устройства; это может быть причиной.

+0

Включили ли вы все необходимые флаги взаимодействия при создании своей библиотеки и приложения? –

+0

Их нет. И команда BLX предполагает, что toolchain знает, что происходит. –

+0

hmmmmm .... Должно быть что-то мы не знаем. Правда, инструкции Thumb были очень ограничены, но Thumb2 - другое животное, даже более эффективное, чем режим ARM. Я думаю, что пришло время сбросить режим ARM и перейти на кодирование в режиме Thumb2. –

ответ

2

У меня есть знание об этом; Я был инженером-реверсом, который выяснил причину в ядре Windows RT. В частности, KeContextFromKframes в ядре Windows NT (ntoskrnl.exe) устанавливает бит T при замораживании состояния потока для переключателя задачи. Это означает, что да, после возобновления после прерывания, вы потерпите крах.

Это раздражало нас джейлбрейками для RT/WinPhone, потому что мы не могли напрямую переносить JITter от Chrome, не нарушая PatchGuard от Microsoft. Мы могли бы загрузить драйвер ядра, чтобы исправить это из KeContextFromKframes, но затем PatchGuard позже выйдет из строя.

0

Вы не можете получить неровный адрес руки при использовании BLX от большого пальца до руки. Нижние два бита подчиняются второй команде. Прочитайте документацию руку, вы в основном имеют две команды первый является:

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. 

Я думаю, что ваша авария где-то в другом месте.

Вы должны опубликовать разборку соответствующего кода, адреса инструкций и т. Д.

, насколько ваша попытка 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. 

через операцию с 1110 вы расчищаете lsbit, но и потенциально позволяя невыровненный адрес. Если вы неправильно вычислили адрес назначения в r12, и если это не код руки, тогда он не будет работать. Пожалуйста, опубликуйте разборки этого, а также ясно покажет, что происходит, также отправьте первую инструкцию или несколько адреса назначения.

Похоже, ваш код исключения сообщает вам, что ваше исключение находится в режиме большого пальца с большим пальцем. Отправьте разборку для кода на/вокруг этого адреса.

2

Джентльмен по имени Michael Schnell suggested elsewhere, что обработчик прерываний в Windows Phone 8 не восстанавливает флаг Thumb, а жестко кодирует его до 1. Тестирование, похоже, подтверждает эту теорию. Следующий фрагмент кода:

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

    ALIGN 4 
    ARM 
a 
    bx lr 

стабильно падает под отладчиком, но работает, как ожидалось, когда debuggerless (то нет прерываний в то время как в режиме ARM..). Когда я вставил пустой цикл с итерациями 0x10000 в режиме ARM, он запускался несколькими попытками, а затем разбился.