Jump to content

    
Sign in to follow this  
Harvester

Странная генерация исключения Misaligned (ARM9)

Recommended Posts

Добрый день.

Процессор ARM926, отладчик - китайский T32.

В процессе портирования кода опять столкнулся с исключением Misaligned. Нашел функцию, ПОСЛЕ возврата из которой возникает упомянутое исключение. Обращаю внимание - именно после возврата. Причем если поставить точку останова на команду, следующую за командой вызова функции, то выполнение программы на ней останавливается как бы без генерации исключения, однако при последующем запуске (RUN или STEP) отладчик пишет "Emulator running", а устройство перезапускается (штатное поведение при фатальной ошибке в рабочем режиме). Т.е. исключение генерируется, но почему-то отладчик его не отслеживает, а, наоборот, "теряет" устройство. То же самое происходит если дойти до этой команды пошагово (при этом неважно, есть там точка останова или нет).

А вот если поставить точку останова на 2-ю команду после команды вызова функции, то до нее программа не доходит, а вылетает в обработчик фатальных ошибок.

Стек в порядке. На всякий случай код функции:

void MainCipherStepWithOptimization (
  PULONG pN,                  // r0 = 01AF4054
  PUCHAR pKey,                // r1 = 01AF408C
  PUCHAR keyIndexes,          // r2 = 00F44E20
  PULONG pSubstTable,         // r3 = 00CA2027 
  unsigned char itCounter
)
{
    ULONG Temp, Idx;
    PULONG pKeyItem = (PULONG)pKey;
    int i;

    for (i = 0; i < itCounter; i++)
    {
        Idx = *pN + pKeyItem[keyIndexes[i]];

        Temp = pSubstTable[((Idx >> 0)  & 0x000000FFUL)        ]
             | pSubstTable[((Idx >> 8)  & 0x000000FFUL) + 0x100]
             | pSubstTable[((Idx >> 16) & 0x000000FFUL) + 0x200]
             | pSubstTable[((Idx >> 24) & 0x000000FFUL) + 0x300];

        Temp ^= *(pN + 1);
      
        *(pN + 1) = *pN;
        *pN = Temp;
    }
    Temp = *pN;
    *pN = *(pN + 1);
    *(pN + 1) = Temp;
}

Единственная зацепка - нечетное значение указателя на массив long-ов pSubsTable. Но если дело в этом, то почему не возникает исключения во время работы функции (при обращении к этому массиву)? Больше ничего криминального не вижу.

Подскажите пожалуйста, что может быть причиной такого поведения - уже всю голову сломал.

Share this post


Link to post
Share on other sites
Единственная зацепка - нечетное значение указателя на массив long-ов pSubsTable. Но если дело в этом, то почему не возникает исключения во время работы функции (при обращении к этому массиву)?

Т.е. отладчик свободно в пошаговом режиме проходит обращения к pSubsTable? Просто исключить в функции обращение к pSubsTable не пробовали?

 

Похоже, Вы просто проблемы работы отладчика наблюдаете. При очевидной причине и месте возникновении исключения. Так зачем голову ломать?

Share this post


Link to post
Share on other sites
Т.е. отладчик свободно в пошаговом режиме проходит обращения к pSubsTable? Просто исключить в функции обращение к pSubsTable не пробовали?

 

Похоже, Вы просто проблемы работы отладчика наблюдаете. При очевидной причине и месте возникновении исключения. Так зачем голову ломать?

Обращения к pSubsTable проходят свободно в любом режиме, как в пошаговом, так и в обычном. При запуске без отладчика исключение тоже генерируется - устройство перезагружается. В общем, как-то не похоже на глюки отладчика.

Попробовал убрать обращение к pSubsTable - поведение не изменилось.

 

Важное дополнение - в первом сообщении была ошибка. Еще раз внимательно проверил: pSubsTable при вызове выровнен на границу двойного слова (r3 = 01064484). Теперь я вообще ничего не понимаю :crying:

Share this post


Link to post
Share on other sites
Важное дополнение - в первом сообщении была ошибка. Еще раз внимательно проверил: pSubsTable при вызове выровнен на границу двойного слова (r3 = 01064484). Теперь я вообще ничего не понимаю :crying:

Тогда это больше похоже на повреждение стека в процессе выполнения функции с перетиранием адреса возврата.

Share this post


Link to post
Share on other sites
Обращения к pSubsTable проходят свободно в любом режиме, как в пошаговом, так и в обычном. При запуске без отладчика исключение тоже генерируется - устройство перезагружается. В общем, как-то не похоже на глюки отладчика.

Попробовал убрать обращение к pSubsTable - поведение не изменилось.

Важное дополнение - в первом сообщении была ошибка. Еще раз внимательно проверил: pSubsTable при вызове выровнен на границу двойного слова (r3 = 01064484). Теперь я вообще ничего не понимаю :crying:

Напишите нормальный обработчик исключения с выводом в лог (UART) содержимого регистров в момент исключения. Какой смысл гадать на кофейной гуще если у Вас при исключении девайс перегружается и информация о причине теряется?

Исключение может быть вообще не в этой функции возникает. Также - в случае невыровненной записи, в некоторых случаях, я думаю, исключение может генериться не сразу, а через неск. команд из-за буферизации записи.

Share this post


Link to post
Share on other sites

В случае, когда сходу ничего не понятно, совет простой: последовательно комментировать операции, которые могут как-то влиять на работу. Я бы начал с последовательного комментирования операций записей. Если не помогает, тогда начал бы комментировать операции чтения. Как только после очередной закоментированной строчки ошибка пропадает, необходимо "помедетировать" над этой строчкой. Не помогла "медитация", комментируем что-нибудь еще и так до полного просветления :-)

Share this post


Link to post
Share on other sites

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

void Gost_EncryptCFB_(PGOST28147_CTX pX)
{
    ULONG *pLB = (ULONG *)pX->pd.prData;
    ...
    MainCipherStepWithOptimization(...);
            *(pLB + 0) ^= pX->N[0];
            *(pLB + 1) ^= pX->N[1];
    ...

Указатель на char явно приводится к указателю на long. Поскольку исходный указатель не выровнен, то при обращении к новому указателю (компилятор использует команды LD/ST) возникает исключение. Чтобы этого избежать надо добавить атрибут packed:

__packed ULONG *pLB = (__packed ULONG *)pX->pd.prData;

В этом случае компилятор подставляет библиотечные функции __rt_uread4/__rt_write4, которые читают/пишут значение побайтно.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this