Как работает отладчик?
Мне интересно, как работает отладчик? В частности, может быть прикреплена к уже исполняемому файлу. Я понимаю, что компилятор переводит код на машинный язык, но тогда как отладчик "знает", к чему он привязан?
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, поплавков, строк и т. д.). Как сказано в первом плакате, эта информация и то, как эти символы работают, во многом зависит от окружающей среды и языка.