Генерация статического вызова для ядра Linux

Я ищу инструмент для статического генерации графика вызовов ядра Linux (для заданной конфигурации ядра). Сгенерированный график вызовов должен быть "полным", в том смысле, что все вызовы включены, в том числе потенциальные косвенные, которые мы можем предполагать, выполняются только с помощью указателей функций в случае ядра Linux.

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

ncc, похоже, реализует эту идею, однако мне не удалось заставить ее работать над ядром 3.0. Любые другие предложения?

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

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

Любая помощь будет высоко оценена.

Ответы

Ответ 1

Мы сделали глобальные аналитические точки (с косвенными указателями функций) и построили график полного вызова монолитных систем С из 26 миллионов строк (18 000 единиц компиляции).

Мы сделали это, используя наш DMS Software Reengineering Toolkit, его C Front End и его связанный механизм анализа потока. Механизмы с точки зрения анализа (и другие анализы) являются консервативными; да, вы получаете некоторые фиктивные точки и, следовательно, вызываете границы. Их довольно трудно избежать. Вы можете помочь таким анализаторам, предоставив некоторые важные факты о ключевых функциях и используя такие знания, как "встроенные системы [и ОС], как правило, не имеют циклов в графике вызовов", что означает, что вы можете устранить некоторые из них. Конечно, вы должны допускать исключения; моя мораль: "в больших системах все происходит".

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

Броски на указатели функций не должны терять края; консервативный анализ должен просто предполагать, что указатель заливки соответствует любой функции в системе с сигнатурой, соответствующей кастинговому результату. Более проблематичными являются отливки, которые производят сопоставимые подписи; если вы наложите указатель на функцию void * foo (uint), когда действительная вызываемая функция принимает int, точки для анализа обязательно консервативно выбирают неправильные функции. Вы не можете обвинять анализатор в этом; в этом случае бросок. Да, мы видели этот вид мусора в 26-миллионной линейной системе.

Это, безусловно, правильная шкала для анализа Linux (я думаю, это всего лишь 8 миллионов строк или около того:-). Но мы не пробовали его конкретно в Linux.

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