Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial Internet of Things >> Встроенный

Навигация по вызовам компилятора в приложениях функциональной безопасности

Во всех отраслях функциональная безопасность накладывает строгие требования на разработчиков: код должен быть защищенно спроектирован для защиты от непредвиденных событий, таких как повреждение памяти или космическое излучение. Языки высокого уровня вроде C и C++ содержат особенности, поведение которых не полностью определено спецификацией языка. Эти неопределенные поведения могут производить удивительные, потенциально катастрофические результаты в системах критической безопасности. Следовательно, стандарты требуют защитного кодирования, строгой тестируемости, комплексного покрытия кода и прослеживаемости от требований к прикладному коду для обеспечения полной и уникальной реализации функций безопасности.

Сектора критической безопасности, особенно автомобильная, часто требуют сложных внешних диагностических, калибровочных и инструментов разработки. Защитное кодирование и внешний доступ к данным — не концепции, которые компиляторы по умолчанию понимают. Ни C, ни C++ не учитывают повреждение памяти, поэтому если защитные меры не явно достижимы в коде, компилятор может оптимизировать их. Защиты должны поэтому оставаться синтаксически и семантически достижимыми, чтобы выжить проходам оптимизации.

Неопределенное поведение ноториально трудно обнаружить. Даже когда идентифицировано, нет гарантии, что скомпилированный бинарник поведет себя как задумано. «Back-door» доступ к данным, используемый инструментами отладки — еще один пример языковых конструкций, которые компиляторы не учитывают, приводящий к непредвиденным побочным эффектам.

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

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

До и после компиляции

Функциональная безопасность, безопасность и стандарты кодирования (IEC 61508, ISO 26262, IEC 62304, MISRA C/C++) подчеркивают необходимость демонстрации того, сколько исходного кода исполняется во время тестирования на основе требований. Хотя высокое покрытие снижает вероятность полевых отказов, оно опирается на предположение, что компилятор верно воспроизводит поведение на уровне исходников — предположение, которое не может быть обосновано для самых критических приложений.

Управление и поток данных сгенерированного объектного кода редко зеркалят исходный код точно. 1:1 отображение между объектным кодом и ассемблером раскрывает расхождения. Например, Рисунок 1 показывает ассемблер, полученный из фрагмента исходника с отключенной оптимизацией с использованием компилятора TI. Когда оптимизация включена, граф потока меняется драматически, потому что компилятор применяет математические трансформации, предполагающие отсутствие неопределенного поведения.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 1: Сравнение исходника vs ассемблер, иллюстрирующее, как оптимизация может изменить поток управления.

Компиляторы могут оптимизировать защитные вызовы, если они определяют, что связанная ветка недостижима. Рисунок 2 демонстрирует компиляцию CLANG, где вызов обработчика ошибки удаляется, потому что компилятор выводит, что переменная состояния может содержать только два значения. Эта оптимизация, хотя и эффективна, нарушает намерение безопасности защитного кодирования.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 2: CLANG удаляет защитный вызов ошибки из-за недостижимой ветки.

Изменение окружающего контекста может изменить решения компилятора об оптимизации. Рисунок 3 добавляет новую функцию, обращающуюся к переменной состояния; компилятор теперь сохраняет защитный вызов, потому что дополнительный контекст делает ветку потенциально выполнимой. Дальнейшие изменения, такие как возврат указателя на состояние, заставляют компилятор сохранять явные значения в ассемблере (Рисунок 4).

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 3: Изменение контекста сохраняет защитную ветку.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 4: Псевдонимизация указателя предотвращает оптимизацию защитного кода.

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

Верификация объектного кода

OCV предоставляет страховку, сравнивая исходник и ассемблер. Рисунок 6 показывает простую функцию, которая, выполненная с единственным тестовым вызовом, достигает 100% покрытия на уровне исходника. Однако собранный граф потока (Рисунок 8) раскрывает неисполненные пути, которые юнит-тест пропустил. Заставляя тесты покрывать все ассемблерные пути, OCV обнаруживает пробелы, которые тесты на уровне исходника упускают.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 6: Исходный код, достигающий 100% покрытия в юнит-тестах.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 7: Граф потока базовых блоков исходника.

Навигация по вызовам компилятора в приложениях функциональной безопасности
Рисунок 8: Собранный граф потока, раскрывающий нетестированные пути.

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

Лучшая практика во всех доменах

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

Встроенный

  1. Почему электробезопасность важна: защита жизни и здоровья
  2. Полное руководство по текстильным красителям: типы, применения и выбор правильного производителя
  3. Как кислотные красители трансформируют ткани: применения и преимущества
  4. Наука текстилей: глубокое погружение в кислотные, реактивные, кожевенные и прямые красители
  5. Корзины безопасности: универсальные решения для работ на высоте и доступа к оборудованию
  6. Как моделирование стимулирует инновации и эффективность в проектировании продуктов
  7. Глобальные производственные сверхдержавы: ключевые столицы, движущие рост отрасли
  8. Топ-5 основных правил безопасности кранов для более безопасных операций
  9. Почему фрикционные материалы критичны для надёжных систем безопасности
  10. Безопасность на заводе: непрерывное улучшение в эпоху Индустрии 4.0