Реализация точек останова, которые безопасно возобновляются в многопоточном коде - PullRequest
0 голосов
/ 30 июня 2018

Я пишу отладчик и в настоящее время пытаюсь заставить точки останова работать надежно, когда несколько потоков сталкиваются с ними одновременно. Насколько я знаю, большинство отладчиков реализуют точки останова, заменяя первый байт инструкции на 0xCC, и именно так я сейчас и делаю. Тем не менее, я не вижу способа восстановить исходный байт, в то же время сохраняя возможность остановить другие потоки, которые собираются достичь этой точки останова, без остановки всех запущенных потоков. У кого-нибудь есть информация о том, как это обычно достигается? Является ли остановка всех потоков действительно единственным решением?

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Я знаю, что временная приостановка всех потоков является распространенным способом решения этой проблемы. Я спрашиваю, есть ли способ избежать этого.

Первый поток, достигший вашей int3 программной точки останова, - это тот, который вы хотите остановить.

Если другие потоки ударили по нему до того, как вы сможете восстановить его до нужного содержимого, возобновите эти потоки после удаления точки останова программного обеспечения. ( x86 имеет согласованные кеши команд , поэтому вы можете безопасно изменять один байт кода без необходимости запуска другими командами ядра / isync инструкций для повторной синхронизации их кешей команд с кешем данных. Это сложнее проблема на других ISA.)

Другие темы могут видеть небольшое прерывание.


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


Проверка и изменение памяти во время работы других потоков потенциально опасны. Другой поток может отключить память непосредственно перед тем, как вы попытаетесь прочитать или изменить ее. До тех пор, пока сам ваш отладчик не дает сбоя, пользователь сам решает, какой беспорядок он хочет создать.

0 голосов
/ 30 июня 2018

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

Остановка только одного потока во время отладки, в то время как другие потоки продолжают работать, просто вызывает проблемы. Подумайте, как бы вы справились с попаданием в ту же или другую точку останова, когда вас останавливали в первый раз? Или если возникает исключение?

На процессорах Intel есть флаг, который можно установить в регистре EFLAGS (флаг возобновления, бит 16). Если установлено, это позволит выполнить первую инструкцию без запуска точек останова и будет работать при использовании аппаратных точек останова (а не команды останова).

Глава 17 тома 3 (Руководство по системному программированию, доступное для загрузки с Intel ) содержит множество подробностей о функциях отладки процессоров Intel IA-32.

...