2009-07-27 5 views
8

В встроенном программном обеспечении, как вы обрабатываете переполнение стека общим способом? Я сталкиваюсь с некоторыми процессорами, которые защищают аппаратным способом, как недавние процессоры AMD. Есть некоторые методы в Википедии, но являются ли они реальными практическими подходами?Обработка переполнения стека во встроенных системах

Может ли кто-нибудь дать понятный подход, который работает во всех случаях на современных 32-битных встроенных процессорах?

+1

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

+0

Независимый от процессора алгоритм или техника. Техника, используемая хакером в среде ПК, может быть применена путем игры с указателями и сбой вашей системы на встроенном sw. Это уменьшает, как защитить обратный адрес в области вашего стека. – 2009-07-27 01:04:37

+1

Переполнением стека вы имеете в виду, когда память стека исчерпана слишком большим количеством стека вызовов? например рекурсивная функция слишком много уровней? Защита обратных адресов больше связана с предотвращением переполнения буфера в стеке, чем «переполнение стека». –

ответ

1

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

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

Существуют инструменты для анализа статического исходного кода, такие как GnatStack, StackAnalyzer от AbsInt и Bound-T, которые могут использоваться для определения или принятия предположения в максимальном размере стека во время выполнения.

2

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

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

Алгоритм проверки шаблона должен выполняться в противоположном направлении роста стека. Таким образом, если стек растет от 0x1000 до 0x2000, то проверка вашего шаблона может начинаться с 0x2000 для повышения эффективности. Если ваш шаблон равен 0xAA, а значение в 0x2000 содержит что-то отличное от 0xAA, вы знаете, что у вас, вероятно, есть переполнение.

Вы также должны рассмотреть возможность размещения пустого RAM-буфера сразу после стека, чтобы, если вы обнаруживаете переполнение, вы можете отключить систему без потери данных. Если за вашим стеком немедленно следуют данные кучи или SRAM, то определение переполнения означает, что вы уже понесли коррупцию. Ваш буфер будет защищать вас немного дольше. На 32-битном микроэлементе у вас должно быть достаточно ОЗУ для обеспечения хотя бы небольшого буфера.

+0

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

+0

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

+0

... и избегайте всех _other_ проблем, которые могут возникнуть вложенные прерывания! –

11

В идеале вы пишете свой код со статическим использованием стека (без рекурсивных вызовов). Затем вы можете оценить максимальное использование стека по:

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

Но даже при этом вы все равно хотите иметь средства обнаружение, а затем обработка переполнение стека, если это происходит, если это вообще возможно, для большей надежности. Это может быть особенно полезно на этапе разработки проекта.Некоторые методы для обнаружения переполнения:

  1. Если процессор поддерживает постоянное запоминающее устройство прерывания/записи (то есть памяти прерывание точки прерывания доступа), то он может быть сконфигурирован, чтобы указать на самой дальней степени области стека.
  2. В конфигурации карты памяти настройте небольшой (или большой) блок ОЗУ, который является областью защиты стека. Заполните его известными значениями. Во встроенном программном обеспечении регулярно (как можно чаще) проверяйте содержимое этой области. Если он когда-либо изменится, предположите переполнение стека.

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

  1. журнал ошибка
    1. Logging ошибки очень полезно, потому что в противном случае симптомы (неожиданные перезагрузки) может быть очень трудно диагностировать.
    2. Предостережение: процедура ведения журнала должна быть надежной и надежной даже в сценарии с поврежденным стеком. Процедура должна быть простой. То есть с поврежденным стеком, вы, вероятно, не можете попытаться записать в EEPROM, используя вашу фантастическую задачу EEPROM. Возможно, просто зарегистрируйте ошибку в структуре, которая зарезервирована для этой цели, в неинтеральной ОЗУ, которая затем может быть проверена после перезагрузки.
  2. Reboot (или, возможно, завершение работы, особенно если ошибка повторяется несколько раз)
    1. Возможная альтернатива: перезапустить только конкретную задачу, если вы используете ОС реального времени, и ваша система разработана таким образом, повреждение стека изолирован, и все остальные задачи могут обрабатывать эту перезагрузку задачи. Это потребует серьезного рассмотрения.
+0

+1 для входа в систему и/или перезагрузки – Gabe

+0

+1 Отличный ответ. –

+0

Есть ли способ для измерения (не статического) использования стека путем переноса каждого вызова функции и проверки указателя стека в оболочке? Меня беспокоит случай, когда переполнение стека падает на bss или данные и вносит изменения, не испорчая «защиту стека». – CodePoet

1

Если вы используете процессор с блоком управления памятью ваше оборудование может сделать это для вас с минимальными затратами программного обеспечения. Большинство современных 32-битных процессоров имеют их и все больше и больше 32-битных микроконтроллеров.

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

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

Я успешно использовал это на процессорах PPC и AVR32. Когда вы начинаете использовать MMU, вы чувствуете, что это пустая трата времени, так как вы отлично справлялись с этим в течение многих лет, но как только вы увидите преимущества исключения в точном месте, где возникает ваша проблема с памятью, вы никогда не вернетесь. MMU также может обнаруживать обращения нулевого указателя, если вы запретите доступ к памяти в нижнем парке вашего бара.

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

В дополнение к этому в процессоре с MMU обычно также много ловушек, ваша программа намного реже переполняет ваш стек, и вам не нужно тонко настраивать все, чтобы вы могли нормально работать с небольшим печать памяти.

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

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