2012-06-18 1 views
1

Я разрабатываю программное обеспечение для встроенного микроконтроллера Cortex-M3 (Atmel SAM3S) Я использую компилятор IAR EWARM IDE &. Я подозреваю, что по какой-то причине у меня переполнение буфера или утечка памяти, что приводит к повреждению стека, потому что я внезапно оказался за пределами моего кодового пространства.обнаружение ошибки перезаписи стека

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

вы используя отладчиков памяти, в цепи отладки аппаратных средств трассировки и т.д.

ответ

2

Программа Счетчик представляет собой регистр, и как таковое оно не может быть «перезаписаны». Что может случиться, так как вы говорите, что стек перезаписывается, а затем вы выполняете команду возврата, которая считывает неверный адрес возврата из стека, тем самым вызывая прыжок в la-la-land.

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

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

+0

Вы правильно относитесь к ПК, я отредактирую свой вопрос. – stdcall

4

Вам следует попробовать использовать канарейки. Вот как это в основном идет - скажем, у вас есть некоторые struct:

struct foo { 
    unsigned long bar; 
    void * baz; 
}; 

Измените его так, это выглядит следующим образом:

struct foo { 
    unsigned long canary1; 
    unsigned long bar; 
    void * baz; 
    unsigned long canary2; 
}; 

При инициализации struct, поставить некоторые произвольные значения в canary1 и canary2. Всякий раз, когда вы выполняете некоторую операцию на своем struct, проверьте, остаются ли значения неизменными. Таким образом, если у вас переполнение буфера или разбивка стека, вы обнаружите его. Вы можете выполнять те же внутренние функции с автоматическими переменными:

int foo(int bar) { 
     unsigned long canary1 = 0xDEADBABE; 
     char baz[20]; 
     unsigned long canary2 = 0xBAD0C0DE; 
     ... 
} 

И так далее. Не забудьте проверить, чтобы значения остались прежними до вас return. Кроме того, если вы можете заставить свой код последовательно переходить в одно и то же место, попробуйте поместить туда некоторый код (или точку останова) и получить трассировку стека.

GCC знает, как добавить эти значения канарейки самостоятельно, но я не знаю, может ли ваш компилятор сделать это. Но вы все равно можете сделать это вручную.

+0

Мы делаем что-то подобное, где мы поместим значение «хозяина» канарейки в конце наших данных и bss (наш стек растет назад с конца). Мы инициализируем значение при запуске и постоянно проверяем его в случае переполнения стека или случайных записей. – shenles

2

У меня была аналогичная проблема с использованием IAR EWARM на STM32. Свалки памяти, разборки, канарейки, все ничего не возникало. Наконец, вернулась к более ранней версии EWARM, и проблема исчезла. Я отправил сообщение в поддержку IAR, но никогда не слышал назад. Извините, я не помню, какая версия EWARM была такой. Это было несколько проектов назад.

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

1

Я могу добавить, что с помощью ARM-чипов возможно, что вместо BLX или BLX был BL, который заставлял чип идти в неправильный режим Thumb/ARM. Не так часто встречается с более поздними фишками, но все же ...

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

Я бы также сделал стандартную информацию о том, что изменилось за последние X дней, чтобы попытаться изолировать любые проблемы. Наконец, просто распечатайте черту из своего кода, чтобы попытаться сузить место, где происходит неудачный прыжок. Если вы можете перевести его на функцию или две, вы можете проследить ассемблер и посмотреть, достаточно ли это проблема компилятора, проблема с памятью или проблема с прерыванием. Удачи!

 Смежные вопросы

  • Нет связанных вопросов^_^