Вот ядро ядра моего ответа: напишите какой-нибудь код.
Суть моего ответа такова: если ваш компилятор всегда размещает локальные данные в стеке, тогда ...
Добавляйте к стеку двоичные объекты при каждом входе в функцию, которые записывают имя функции, добавьте несколько магических чисел, чтобы, возможно, перехватить стеки.
typedef struct stack_debug_blob_ {
int magic1;
const char * function_name;
int magic2;
struct stack_debug_blob_ * called_by;
int magic3;
} stack_debug_blob;
stack_debug_blob * top_of_stack_debug_blobs = 0;
Создание макроса ENTER (f) с именем функции. Макрос должен быть около первой строки кода в каждой функции после открытия {. Он добавляет структуру с указателем на (const) имя функции char *, указатель на предыдущую структуру в стеке и, возможно, некоторые магические числа для проверки работоспособности. Наведите указатель на вершину стека BLOB-объектов на эту новую структуру.
#define ENTER(f) \
stack_debug_blob new_stack_debug_blob = { \
MAGIC1, (f), MAGIC2, top_of_stack_debug_blobs, MAGIC3}; \
stack_debug_blob * evil_hack = (top_of_stack_debug_blobs = (&new_stack_debug_blob))
Чтобы сделать вещи максимально переносимыми, все, что может сделать ENTER, это объявить и инициализировать переменные. Следовательно, evil_hack делает немного больше вычислений, чем просто инициализирует переменную.
Создать функцию для просмотра списка BLOB-объектов, проверяющих указатели и магические числа. Он должен сигнализировать об ошибке (возможно, печать в stderr, возможно, заблокировать процессор с помощью while (1) {/ * nada * /}, возможно, войти в отладчик ... зависит от вашего оборудования), если он обнаружит, что что-то не так.
Создайте макрос EXIT (), который проверяет ваш стек больших двоичных объектов, а затем удаляет самые верхние ссылки из связанного списка. Его нужно поместить в точки выхода всех ваших функций.
#define EXIT() do { \
check_debug_blobs(); \
top_of_stack_debug_blobs = new_stack_debug_blob.called_by; \
new_stack_debug_blob.magic1 -= 1; /* paranoia */ \
} while (0)
Вероятно, потребуется также заменить все возвраты вызовами макроса RETURN, макрос RETURN аналогичен EXIT, но имеет возврат до} while (0).
Создайте функцию, чтобы пройтись по списку больших двоичных объектов, распечатывая имена функций, назовите ее, например, как stacktrace или backtrace.
Напишите программу для инструментов вашего кода C с вызовами ENTER (f) и EXIT () и RETURN (x).
Оставьте несколько деталей, чтобы вы могли с ним повеселиться ...
См. Также Доступно ли какое-либо портирование backtrace для uclibc?