Я пишу отладчик и в настоящее время пытаюсь заставить точки останова работать надежно, когда несколько потоков сталкиваются с ними одновременно. Насколько я знаю, большинство отладчиков реализуют точки останова, заменяя первый байт инструкции на 0xCC, и именно так я сейчас и делаю. Тем не менее, я не вижу способа восстановить исходный байт, в то же время сохраняя возможность остановить другие потоки, которые собираются достичь этой точки останова, без остановки всех запущенных потоков. У кого-нибудь есть информация о том, как это обычно достигается? Является ли остановка всех потоков действительно единственным решением?
Когда все потоки остановлены, вы восстанавливаете этот байт, шаг только одна нить для одной инструкции воссоздайте точку останова, затем возобновите выполнение всех потоков. Если вы используете один из ограниченных аппаратных регистров отладки, вы можете использовать RF, чтобы временно игнорировать точку останова для одной инструкции (см. Ниже).
Остановка только одного потока во время отладки, в то время как другие потоки продолжают работать, просто вызывает проблемы. Подумайте, как бы вы справились с попаданием в ту же или другую точку останова, когда вас останавливали в первый раз? Или если возникнет исключение?
На процессорах Intel есть флаг, который можно установить в регистре EFLAGS (флаг возобновления, бит 16). Если установлено, это позволит выполнить первую инструкцию без запуска точек останова и будет работать при использовании аппаратных точек останова (а не команды останова).
Глава 17 тома 3 (Руководство по системному программированию, доступно для скачать с Intel) содержит много подробностей о функциях отладки процессоров Intel IA-32.
Я знаю, что временная приостановка всех потоков является распространенным способом решения этой проблемы. Я спрашиваю, есть ли способ избежать этого.
Первый поток, чтобы ударить ваш int3
программная точка останова это та, которую вы хочу прекратить.
Если другие потоки ударили по нему до того, как вы сможете восстановить его до нужного содержимого, возобновите эти потоки после удаления точки останова программного обеспечения. (x86 имеет последовательный кеш инструкций, так что вы можете безопасно изменять один байт кода без необходимости использования других ядер. isync
Инструкция по повторной синхронизации их кэшей команд с кэшем данных. Это сложная проблема для других ISA.)
Другие темы могут видеть небольшое прерывание.
Конечно, если пользователь поместит точку останова в критическую секцию (с удерживаемой блокировкой) или пошагово в критическую секцию, другие потоки заблокируют это. Это также возможно для кода без блокировки, который не без блокировки (в смысле информатики).
Изучение и изменение памяти во время работы других потоков потенциально опасно. Другой поток может удалить память непосредственно перед тем, как вы попытаетесь прочитать или изменить ее. До тех пор, пока сам ваш отладчик не дает сбоя, пользователь сам решает, какой беспорядок он хочет создать.