Как работает отладчик?

Мне интересно, как работает отладчик? В частности, может быть прикреплена к уже исполняемому файлу. Я понимаю, что компилятор переводит код на машинный язык, но тогда как отладчик "знает", к чему он привязан?

6 ответов


детали того, как работает отладчик, будут зависеть от того, что вы отлаживаете, и что такое ОС. Для родной отладки в Windows вы можете найти некоторые сведения о MSDN:Win32 Debugging API.

пользователь сообщает отладчику, к какому процессу присоединяться, по имени или по идентификатору процесса. Если это имя, то отладчик будет искать идентификатор процесса, и начать сеанс отладки с помощью системного вызова; под Windows это будет DebugActiveProcess.

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

отладчик может читать и записывать виртуальную память целевого процесса и даже корректировать его значения регистра через API, предоставляемые ОС. См. список функции отладки для Windows.

отладчик может использовать информацию из файлов символов для перевода с адресов на имена переменных и местоположения в исходном коде. Информация о файле символов представляет собой отдельный набор API и не является основной частью ОС как таковой. На Windows это через отладка интерфейса доступа SDK.

Если вы отлаживаете управляемую среду (.NET, Java и т. д.) процесс обычно они выглядят похожими, но детали отличаются, так как среда виртуальной машины предоставляет API отладки, а не базовую ОС.


как я понимаю:

для точек останова программного обеспечения на x86 отладчик заменяет первый байт инструкции на CC (int3). Это делается с WriteProcessMemory на Windows. Когда CPU получает эту инструкцию и выполняет int3, это заставляет CPU генерировать исключение отладки. ОС получает это прерывание, понимает, что процесс отлаживается, и уведомляет процесс отладчика о том, что точка останова была поражена.

после попадания в точку останова и остановки процесса отладчик просматривает список точек останова и заменяет CC с байтом, который был там изначально. Отладчик устанавливает TF, флаг ловушки на EFLAGS (путем изменения CONTEXT), и продолжается процесс. Флаг Trap заставляет CPU автоматически генерировать одношаговое исключение (INT 1) на следующий инструкция.

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

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


в Linux отладка процесса начинается с ptrace (2) системный вызов. в этой статье имеет большой учебник о том, как использовать ptrace для реализации некоторых простых отладочных конструкций.


Если вы находитесь в ОС Windows, отличным ресурсом для этого будет "отладка приложений для Microsoft .NET и Microsoft Windows" Джона Роббинса:

(или даже более старое издание:"Отладка Приложения")

в книге есть глава о том, как работает отладчик, которая включает код для нескольких простых (но работающих) отладчиков.

Так как я не знакомый с деталями отладки Unix/Linux, этот материал может вообще не применяться к другим ОС. Но я бы предположил, что в качестве введения в очень сложный предмет концепции - если не детали и API - должны "портировать" большинство любых ОС.


другим ценным источником для понимания отладки является руководство Intel CPU (архитектуры Intel® 64 и IA-32 Руководство разработчика программного обеспечения). В томе 3А, Глава 16, он представил аппаратную поддержку отладки, такую как специальные исключения и аппаратные отладочные регистры. Из этой главы следует:

t (trap) флаг, TSS-генерирует исключение отладки (#DB), когда попытка сделано для переключения на задачу с флагом T, установленным в его TSS.

Я не уверен использует ли Window или Linux этот флаг или нет, но очень интересно прочитать эту главу.

надеюсь, это кому-то поможет.


Я понимаю, что при компиляции приложения или DLL-файла все, что он компилирует, содержит символы, представляющие функции и переменные.

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