Як GDB призупиняє виконання


16

Як ви можете знати, ми можемо використовувати GDB і встановлювати точки перерви в нашому коді, щоб призупинити виконання для налагодження.

Мої запитання: як GDB призупиняє процес і дозволяє переглядати вміст регістрів, використовуючи, i rнаприклад. Чи не постійно такі регістри використовуються іншими процесами ОС? як їх не перезаписати?

Це лише знімок вмісту, а не живі дані?


2
Чому всі регістри не перезаписуються, коли ОС вирішує на мить призупинити вашу програму та запустити інший?
користувач253751

CppCon 2018: Бренд Саймона “Як працюють налагоджувачі C ++” youtube.com/watch?v=0DDrseUomfU
Роберт Анджежук

Відповіді:


24

Це дещо відрізняється від архітектури, але важливі моменти застосовуються майже повсюдно:

  • Обслуговування переривань призводить до збереження стану процесора (включаючи регістри) до пам’яті перед запуском ISR та відновлення після закінчення ISR.

  • Якщо звичайна послуга переривання заміняє вміст місця пам'яті, де зберігаються ці регістри, він може виконати контекстний перемикач . Кожен потік має область пам'яті, де зберігаються його регістри, коли потік не працює.

  • Контекстним комутатором керує планувальник потоків, який враховує, чи чекає поток на введення / виведення, синхронізацію, який його пріоритет, подача сигналу тощо. Часто існує кількість зупинок, на які враховується.

  • Налагоджувач може збільшити кількість призупинень, що гарантує, що нитка не працює. Тоді він може перевірити (і змінити) збережену копію регістрів потоку.


14

На додаток до чудової інформації від @BenVoigt, дозвольте мені внести деякі доповнення:

Точка розриву встановлюється налагоджувачем шляхом заміни значення машинного коду (інструкція або частина інструкції) у процесі налагодження на певну інструкцію пастки у місці в коді, що відповідає бажаному рядку (джерела), на який потрібно перерватися. Ця конкретна інструкція щодо пастки призначена для використання в якості точки перерви - відладчик це знає, як і операційна система.

Коли налагоджений процес / потік потрапляє на інструкцію про пастку, це запускає процес @Ben описує, що включає половину контекстної заміни, яка призупиняє поточний поточний потік (що включає збереження його стану CPU в пам'яті) для можливого подальшого відновлення. Оскільки ця пастка є ловушкою точки перерви, операційна система зберігає процес налагодження призупинення, використовуючи, можливо, механізм @Ben описує, та повідомляє і врешті-решт відновлює відладчик.

Тоді відладчик використовує системні виклики, щоб отримати доступ до збереженого стану відключеного призупиненого процесу / потоку.

Щоб виконати (відновити) рядок коду, який порушився (який тепер має конкретну інструкцію щодо пастки), налагоджувач відновить початкове значення машинного коду, яке він перезаписав, з інструкцією щодо лову точки переривання, можливо, встановить іншу пастку десь в іншому місці (наприклад, якщо один крок, або користувач робить нові точки перерви) і позначте процес / потік як запущений, можливо, використовуючи механізм, як описано @Ben.

Фактичні деталі можуть бути складнішими, оскільки тримати довгу точку розриву, яка потрапила, означає зробити щось на кшталт заміни пастки точки перерви на справжній код, щоб ця лінія могла працювати, а потім знову міняти точку розриву ...

Чи не постійно такі регістри використовуються іншими процесами ОС? як їх не перезаписати?

Як описано @Ben, використовуючи вже існуючу функцію призупинення / відновлення потоку (контекстна комутація / заміна багатозадачності ), яка дозволяє обмінюватися процесорами на декілька процесів / потоків, використовуючи зрізання часу.

Це лише знімок вмісту, а не живі дані?

Це і те, і інше. Оскільки потік , який потрапив в точку зупину призупиняється, це знімок з даних в реальному часі (регістри процесора, і т.д ..) в момент припинення і авторитетний майстер значень регістрів процесора для відновлення в процесор повинен бути поточно відновленої . Якщо ви користуєтесь інтерфейсом користувача налагоджувача для читання та / або зміни регістрів процесора (процесу налагодження), він зчитує та / або змінить цей знімок / майстер за допомогою системних викликів.


1
Ну, більшість архітектур процесорів підтримують пастки налагодження, які, наприклад, спрацьовують, коли IP (покажчик інструкції) дорівнює адресу, що зберігається в реєстрі точок розриву, економлячи необхідність перезаписати код. (Зіставивши реєстри, крім IP, ви можете отримати точки точки переривання даних, і, захопившись після кожної інструкції, ви можете отримати одинарне крокування) Те, що ви описали, також можливе, звичайно, якщо код не знаходиться в пам'яті, що читається тільки.
Бен

Повторно "Якщо ви зміните регістри процесора ..." в останньому пункті, я думаю, ви маєте на увазі "Якщо ви зміните збережену копію реєстрів CUP ..." Потім, коли ОС відновить процес, змінені дані записуються назад до реальних регістрів.
jamesqf

@jamesqf, так, thx!
Ерік Ейдт

@BenVoigt, погодився. хоча в той час як налагоджувачі можуть обробляти необмежену кількість точок перерви, апаратне забезпечення може обробити нуль або декілька, тож налагоджувач повинен виконати кілька жонглювання.
Ерік Ейдт

@jamesqf: Опис того, що копія трохи вводить в оману. Це офіційне сховище для стану потоку, поки потік не працює.
Бен

5

Строго кажучи, принаймні в більшості типових випадків, сам gdb не призупиняє виконання. Швидше, gdb запитує ОС, а ОС призупиняє виконання.

Це може спочатку здатися відмінністю без різниці - але, чесно кажучи, дійсно є різниця. Різниця полягає в тому, що ця здатність вже вбудована в типову ОС, тому що вона повинна бути в змозі призупинити і повторно запустити виконання потоку в будь-якому випадку - коли потік не планується запускати (наприклад, йому потрібен ресурс, який наразі недоступно) ОС потрібно робити паузу, поки її не можна буде запланувати.

Для цього в ОС зазвичай є блок пам'яті, відведений для кожного потоку, щоб зберегти поточний стан машини. Коли потрібно призупинити нитку, поточний стан машини зберігається в цій області. Коли потрібно відновити потік, стан машини відновлюється з цієї області.

Коли налагоджувачу потрібно призупинити потік, він має паузу в ОС, яка робить паузу точно так само, як це було б з інших причин. Потім, щоб прочитати стан призупиненої нитки, налагоджувач дивиться на збережений стан потоку. Якщо ви модифікуєте стан, налагоджувач записує у збережений стан, коли він набуває чинності, коли потік відновиться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.