Есть ли программный способ проверить повреждение стека

Это - мое нормальное предпочтение:

....SELECT column1
........,column2
....FROM table1
....WHERE column3 IN (
........SELECT TOP(1) column4
........FROM table2
........INNER JOIN table3
............ON table2.column1 = table3.column1
....)

, Хотя stackoverflow портит форматирование с дополнительным ведущим пространством, таким образом, я вставил несколько периодов, таким образом, Вы видите, что фактическое форматирует...

9
задан Alphaneo 15 September 2009 в 01:35
поделиться

8 ответов

В последнее время, работая над встроенной платформой, я тщательно искал способы сделать это (это было на ARM7).

Предлагаемое решение было тем, что вы уже придумали: инициализировать стек с использованием известного шаблона и убедиться, что этот шаблон существует после возврата из функции. Я подумал о том же: «Должен быть способ получше» и «Разве это не автоматизировал кто-то». Ответом на оба вопроса было «Нет», и мне пришлось копаться, как и вам, чтобы попытаться найти, где происходит коррупция.

Я также «свернул свои собственные» векторы исключений для data_abort и т. Д. В сети есть несколько отличных примеров того, как проследить стек вызовов. Это то, что вы могли бы сделать с помощью отладчика JTAG, break, когда возникает любой из этих векторов прерывания, а затем исследует стек. Это может быть полезно, если у вас есть только 1 или 2 точки останова (что кажется нормой для отладки ARM JTAG).

4
ответ дан 4 December 2019 в 07:48
поделиться

ARM9 имеет встроенную поддержку отладки JTAG / ETM; у вас должна быть возможность настроить точку наблюдения за доступом к данным, охватывающую, например, 64 байта в верхней части ваших стеков, что затем вызовет прерывание данных, которое вы могли бы зафиксировать в своей программе или извне.

(Оборудование, с которым я работаю только поддерживает 2 точки наблюдения для чтения / записи, не уверен, является ли это ограничением встроенного оборудования или окружающего стороннего отладочного комплекта.)

Этот документ , который представляет собой чрезвычайно низкоуровневое описание того, как взаимодействовать с функциональностью JTAG, предлагает вам прочитать Техническое справочное руководство вашего процессора - и я могу поручиться, что в главе 9 («Поддержка отладки») для ARM946E содержится приличный объем высокоуровневой информации. -S r1p1 TRM .

Прежде чем углубляться в понимание всего этого (если вы не делаете это просто для развлечения / обучения), еще раз проверьте, что используемое вами оборудование и программное обеспечение уже не управляют точками останова / точками наблюдения за вас. Понятие «точки наблюдения» было немного сложно найти в используемом нами программном обеспечении для отладки - это была вкладка с надписью «Оборудование» в диалоговом окне добавления точки останова.


Другая альтернатива: ваш компилятор может поддерживать параметр командной строки для добавлять вызовы функций в точках входа и выхода функций (что-то вроде "void enterFunc (const char * callFunc)" и "void exitFunc (const char * callFunc)") для профилирования стоимости функции, более точной трассировки стека или аналогичных . Затем вы можете написать эти функции для проверки канареечного значения вашего стека.

(Кстати, в нашем случае мы фактически игнорируем переданное имя функции (я бы хотел, чтобы компоновщик разделил их) и просто используем значение регистра связи процессора (LR) для записи того, откуда мы пришли. Мы используем это для получения точных данных о звонках, а также для профилирования информации; проверка канареек стека на этом этапе тоже была бы тривиальной!)

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


Очень позднее обновление: в наши дни, если у вас есть конвейер на основе clang + LLVM, вы можете использовать Address Sanitizer (ASAN) , чтобы отловить некоторые из них. Следите за похожими функциями в своем компиляторе! (Стоит знать о UBSAN и других дезинфицирующих средствах.)

8
ответ дан 4 December 2019 в 07:48
поделиться

Какой компилятор вы используете? Я предполагаю, что это конкретная ОС. Если вы используете GCC, вы можете использовать Stack-Smashing Protector . Это может быть исправление для вашей производственной системы, предотвратит проблему, а также позволит вам обнаружить ее в процессе разработки.

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

6
ответ дан 4 December 2019 в 07:48
поделиться

Я сделал именно то, что вы предложили для dsPIC, используя CMX-Tiny +, однако при проверке стека я также сохраняю «отметку прилива» для каждого стека. Вместо того, чтобы проверять значение наверху стека, я выполняю итерацию сверху, чтобы найти первое значение, не являющееся сигнатурой, и, если оно выше, чем ранее, я сохраняю его в статической переменной. Это выполняется в задаче с самым низким приоритетом, так что она выполняется всякий раз, когда ничего не запланировано (по сути, заменяя цикл простоя; в вашей ОСРВ вы можете перехватить цикл ожидания и сделать это там). Это означает, что он обычно проверяется чаще, чем периодическая проверка 10 мс; за это время можно было бы испортить весь планировщик.

Моя методика состоит в том, чтобы увеличить размер стеков, проверить код, затем проверьте отметки прилива, чтобы определить запас для каждой задачи (и стек ISR - не забывайте об этом!), и соответствующим образом отрегулируйте стеки, если мне нужно восстановить `` потраченное впустую '' пространство из стека большого размера (я не не беспокойтесь, если пространство не требуется).

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

Некоторые ОСРВ имеют эту функцию. встроенный (embOS, vxWorks, о которых я знаю). ОС, которые используют оборудование MMU, могут работать лучше, если поместить стек в защищенное пространство памяти, так что переполнение вызывает прерывание данных. Это лучший способ возможно, вы ищете; ARM9 имеет MMU, но ОС, которые его поддерживают, обычно стоят дороже. Возможно, QNX Neutrino?

Дополнительное примечание

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

Клиффордом.

Возможно, QNX Neutrino?

Дополнительное примечание

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

Клиффордом.

Возможно, QNX Neutrino?

Дополнительное примечание

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

Клиффордом.

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

Клиффордом.

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

Клиффордом.

3
ответ дан 4 December 2019 в 07:48
поделиться

Как упоминает Ли, лучше всего перенести Electric Fence на свой проприетарный компилятор ARM9. В противном случае ARM ABI и формат стека хорошо документированы, поэтому вы могли бы написать функцию CHECK_STACK, которая проверяет, что адреса возврата указывают на функции и т. Д.

Однако трудно по-настоящему написать некоторые из этих проверок, если только вы: re компилятор, поэтому, если вы не особо привязаны к этому компилятору, GCC поддерживает ARM, а также поддерживает защиту стека.

2
ответ дан 4 December 2019 в 07:48
поделиться

Есть ли у вас исходный код ядра? В последний раз, когда я писал ядро, я добавил (в качестве опции) проверку стека в самом ядре.

Когда бы ни происходило переключение контекста, ядро ​​проверяло 2 стека:

(1) Выкладываемая задача -> если задача разорвала свой стек во время работы, дайте знать прямо сейчас.

(2) Целевая (целевая) задача -> до того, как мы переходите к новой задаче, давайте удостоверимся, что какой-то дикий код не сбил ее стек. Если его стек поврежден, даже не переключайтесь на задачу, мы облажались.

Теоретически можно проверить стеки всех задач, но в приведенных выше комментариях объясняется, почему я проверил эти 2 стека (настраивается) .

В дополнение к этому, код приложения может отслеживать задачи (в т.ч.

2
ответ дан 4 December 2019 в 07:48
поделиться

Ответьте на эти похожие вопросы: обработка переполнения стека во встроенных системах и как я могу визуализировать использование sram памяти программой avr .

Лично я бы использовал блок управления памятью вашего процессора, если он есть. Он может выполнять проверку памяти с минимальными затратами программного обеспечения.

Настройте область памяти в MMU, которая будет использоваться для стека. Он должен быть ограничен двумя областями памяти, к которым MMU не разрешает доступ. Когда ваше приложение запущено, вы получите исключение / прерывание, как только переполните стек.

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

2
ответ дан 4 December 2019 в 07:48
поделиться

Ideally valgrind would support your platform/OS. It's shocking to me that you don't get a separate vm memory region for each thread's stack. If there's any way to build your app so it can run on linux as well, you can probably reproduce the bug there and catch it with valgrind.

1
ответ дан 4 December 2019 в 07:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: