Мені цікаво, як працює налагоджувач? Окремий той, який можна "прикріпити" до вже запущеного виконуваного файлу. Я розумію, що компілятор переводить код на машинну мову, але тоді як налагоджувач "знає" до чого він додається?
Мені цікаво, як працює налагоджувач? Окремий той, який можна "прикріпити" до вже запущеного виконуваного файлу. Я розумію, що компілятор переводить код на машинну мову, але тоді як налагоджувач "знає" до чого він додається?
Відповіді:
Деталі того, як працює налагоджувач, залежатимуть від того, що ви налагоджуєте, і що таке ОС. Для власної налагодження в Windows ви можете знайти деякі відомості про MSDN: Win32 API налагодження .
Користувач повідомляє налагоджувачу, до якого процесу слід приєднатися, або за іменем, або за ідентифікатором процесу. Якщо це ім'я, то налагоджувач шукає ідентифікатор процесу та ініціює сеанс налагодження через системний виклик; під Windows це буде DebugActiveProcess .
Після приєднання налагоджувач буде входити в цикл подій так само, як і для будь-якого інтерфейсу, але замість подій, що надходять із системи вікон, ОС генеруватиме події на основі того, що відбувається в процесі налагодження - наприклад, винятку, що відбувається. Дивіться WaitForDebugEvent .
Відладчик здатний читати та записувати віртуальну пам'ять цільового процесу та навіть коригувати його регістрові значення через API, надані ОС. Дивіться список функцій налагодження для Windows.
Налагоджувач може використовувати інформацію з символьних файлів для перекладу з адрес до імен змінних та місць у вихідному коді. Інформація про файл символів є окремим набором API та не є основною частиною ОС як такої. У Windows це відбувається через SDK для доступу до інтерфейсу налагодження .
Якщо ви налагоджуєте кероване середовище (.NET, Java тощо), процес зазвичай буде схожим, але деталі відрізняються, оскільки середовище віртуальної машини забезпечує API налагодження, а не базову ОС.
Як я це розумію:
Для програмних точок переривання на x86 відладчик замінює перший байт інструкції на CC
( int3
). Це робиться за допомогою WriteProcessMemory
Windows. Коли ЦП потрапляє до цієї інструкції та виконує це int3
, це призводить до того, що ЦП генерує виняток налагодження. ОС отримує це переривання, розуміє, що процес налагоджується, і повідомляє про процес налагодження, що точка поломки потрапила.
Після того, як точка перерви буде досягнута і процес зупинений, налагоджувач шукає у своєму списку точок перерви та замінює CC
байт, який був там спочатку. Налагоджувач встановлює TF
прапор пастки в EFLAGS
(шляхом зміни CONTEXT
) і продовжує процес. Прапор пастки змушує ЦП автоматично генерувати одношаговий виняток ( INT 1
) у наступній інструкції.
Коли налагоджений процес зупиняється в наступний раз, відладчик знову замінює перший байт інструкції з точки розриву CC
, і процес продовжується.
Я не впевнений, чи саме так він реалізований усіма налагоджувачами, але я написав програму Win32, яка вдається відлагодити себе за допомогою цього механізму. Повністю марний, але навчальний.
У Linux налагодження процесу починається з виклику системи ptrace (2) . У цій статті є чудовий посібник про те, як використовувати ptrace
для реалізації деяких простих конструктів налагодження.
(2)
говорить нам щось більше (або менше), ніж "ptrace - це системний виклик"?
(2)
номер розділу вручну. Дивіться en.wikipedia.org/wiki/Man_page#Manual_sections для опису розділів посібника.
ptrace
це системний виклик.
(2)
говорить нам про те, що ми можемо набрати man 2 ptrace
та отримати потрібну сторінку сторінки - тут не важливо, тому що немає іншого ptrace
для роз'єднання, але для порівняння man printf
з man 3 printf
Linux.
Якщо ви працюєте в ОС Windows, відмінним ресурсом для цього буде "Налагодження програм для Microsoft .NET і Microsoft Windows" Джона Роббінса:
(або навіть старіше видання: "Налагодження програм" )
У книзі є розділ про те, як працює налагоджувач, який включає код для пари простих (але працюючих) налагоджувачів.
Оскільки я не знайомий з деталями налагодження Unix / Linux, цей матеріал може взагалі не застосовуватися до інших ОС. Але я б здогадався, що як вступ до дуже складної теми поняття - якщо не деталі та API - повинні "портувати" для більшості будь-якої ОС.
Ще одне цінне джерело для розуміння налагодження - посібник з процесора Intel (Інструкція з розробника програмного забезпечення для архітектури Intel® 64 та IA-32). У томі 3A, глава 16, він представив апаратну підтримку налагодження, такі як спеціальні винятки та апаратні регістри налагодження. Далі йде з цієї глави:
Прапор T (пастка), TSS - Створює виняток налагодження (#DB), коли робиться спроба переключитися на завдання із встановленим у його TSS прапором T.
Я не впевнений, що Window або Linux використовують цей прапор чи ні, але дуже цікаво читати цю главу.
Сподіваюся, що це комусь допоможе.
Я думаю, що тут є два основні питання:
1. Як налагоджувач знає, що стався виняток?
Коли в процесі налагодження відбувається виняток, про налагоджувач отримує сповіщення ОС перед тим, як будь-яким обробникам виключень користувачів, визначеним у цільовому процесі, буде надана можливість відповісти на виняток. Якщо налагоджувач вирішив не обробляти це сповіщення про виключення (з першого шансу), диспетчерська послідовність винятків продовжується далі, і цільовий потік отримує можливість обробляти виняток, якщо він хоче це зробити. Якщо виняток SEH не обробляється цільовим процесом, потім налагоджувачу надсилається інша подія налагодження, яка називається сповіщенням про інший шанс, щоб повідомити про те, що в цільовому процесі стався необроблений виняток. Джерело
2. Як відладчик знає, як зупинитися на точці розриву?
Спрощена відповідь : Коли ви вводите точку розриву в програму, налагоджувач замінює ваш код в цій точці інструкцією int3, яка є програмним перериванням . В результаті програма призупиняється і викликається відладчик.
Я розумію, що коли ви компілюєте додаток або файл DLL, те, що він компілює, містить символи, що представляють функції та змінні.
Коли у вас є збірка налагодження, ці символи набагато детальніше, ніж коли це збірка релізів, що дозволяє налагоджувачу давати більше інформації. Коли ви приєднуєте налагоджувач до процесу, він переглядає, до яких функцій зараз доступний, і вирішує всі доступні символи налагодження звідси (оскільки він знає, як виглядає внутрішня інформація компільованого файлу, він може визначити, що може бути в пам'яті , із вмістом ints, floats, strings тощо). Як і в першому плакаті, ця інформація та те, як ці символи сильно працюють, залежать від середовища та мови.