Я не уверен, что полностью понимаю вопрос, но могу рассказать, как GDB реализует свою команду step
.
Как только управление вошло в конкретный модуль компиляции, GDB считывает информацию об отладке этого CU; в частности, он читает часть CU раздела .debug_line и создает таблицу, которая отображает адреса команд в позиции исходного кода.
Когда начинается step
, GDB ищет местоположение источника для текущего ПК. Затем он выполняет пошаговые инструкции, каждый раз просматривая местоположение источника нового ПК, пока местоположение источника не изменится. Когда местоположение источника изменяется, step
завершено.
Он также вычисляет идентификатор кадра - базовый адрес кадра стека и начальный адрес функции - после каждого шага и проверяет, изменился ли он. Если это так, это означает, что мы вступили в рекурсивный вызов или вернулись с него, и step
завершен.
Чтобы понять, почему необходимо проверить идентификатор кадра, а также местоположение источника, рассмотрите возможность перехода к следующей функции:
int fact(n) { if (n > 0) { return n * fact(n-1); } else return 1; }
Поскольку эта функция определена полностью в одной и той же исходной строке, пошаговое выполнение инструкции до тех пор, пока не будет изменена исходная строка, будет выполнять все рекурсивные вызовы без остановки. Однако, когда мы вводим новый вызов факта, базовый адрес кадра стека изменится, что указывает на то, что мы должны остановиться. Это дает нам следующее поведение:
fact (n=10) at recurse.c:4
(gdb) step
fact (n=9) at recurse.c:4
(gdb) step
fact (n=8) at recurse.c:4
Команда
GDB next
объединяет это общее поведение с соответствующей логикой для распознавания вызовов функций и их возврата к завершению. Как и прежде, необходимо использовать идентификаторы кадров при принятии решения, когда вызовы действительно вернулись к исходному кадру; и есть другие осложнения.
Стоит немного подумать о том, как обрабатывать встроенные экземпляры функций (которые описывает DWARF). Но это немного для этого вопроса.
Не для того, чтобы препятствовать экспериментам, но если бы я начинал проект отладчика, я хотел бы взглянуть на отладчик Apple в процессе разработки, lldb , который является открытым исходным кодом.