Добрый день.
Скажите, кто-нибудь пользовался отладочными регистрами (debug registers)?
Если да, то опишите, пожалуйста, алгоритм установки простейшего watchpoint'а, например?
Моя проблема в том, что не получается установить watchpoint локально для одной задачи — он ставится ТОЛЬКО глобально (на все процессы системы). Да, читал, что есть отдельные биты для установки локальных, отдельно для установки глобальных watchpoint'ов. Но не работает.
Здравствуйте, finist_, Вы писали:
_>Добрый день. _>Скажите, кто-нибудь пользовался отладочными регистрами (debug registers)? _>Если да, то опишите, пожалуйста, алгоритм установки простейшего watchpoint'а, например? _>Моя проблема в том, что не получается установить watchpoint локально для одной задачи — он ставится ТОЛЬКО глобально (на все процессы системы). Да, читал, что есть отдельные биты для установки локальных, отдельно для установки глобальных watchpoint'ов. Но не работает. :(
--
Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится.
_>Заранее спасибо!
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится.
--
Ещё раз — спасибо за ответ. Но в связи с этим — ещё один вопрос: ведь MS Visual Studio как-то реализует аппаратные watchpoint'ы! я проверял! И по времени выполнения очень хорошо видно, когда watch аппаратный, а когда программный.
Как же они делают это?
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится.
--
Да, и ещё — а что такое "другие TSS, но они связаны с выполнением нормального кода"? Что такое "нормальный код" и чем он отличается от ненормального. И как сделать нормальный код, чтобы этими TSS'ами винда пользовалась.
Здравствуйте, finist_, Вы писали:
_>Здравствуйте, Геннадий Майко, Вы писали:
ГМ>>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится.
_>-- _>Да, и ещё — а что такое "другие TSS, но они связаны с выполнением нормального кода"? Что такое "нормальный код" и чем он отличается от ненормального. И как сделать нормальный код, чтобы этими TSS'ами винда пользовалась.
--
Здесь моя опечатка — следует читать "но они не связаны с выполнением нормального кода".
ГМ>>>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится. ГМ>Здесь моя опечатка — следует читать "но они не связаны с выполнением нормального кода".
--
Простите мою непонятливость, но вот что мне пришло в голову: TSS — Task-State Segment. По-русски, контекст процесса, вроде. Да, конечно, в процессоре место под него одно. Но ведь у каждого процесса свой контекст? Потому и есть понятие "смена контекста" — когда переключаются процессы, состояния регистров старого процесса виндой должно куда-то записываться, а потом извлекаться обратно, когда процесс сможет продолжить выполнение. Таким образом, мне стало совсем непонятно, как может котекст процесса (TSS) быть не связан с выполнением "нормального кода".
Здравствуйте, finist_, Вы писали:
ГМ>>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится.
_>-- _>Ещё раз — спасибо за ответ. Но в связи с этим — ещё один вопрос: ведь MS Visual Studio как-то реализует аппаратные watchpoint'ы! я проверял! И по времени выполнения очень хорошо видно, когда watch аппаратный, а когда программный. _>Как же они делают это?
--
Точно сказать не могу, как они это делают.
Можно, наверное, запомнить информацию о процессе/потоке перед установкой watchpoint и затем, при ее срабатывании, дополнительно сравнивать ее с информацией о текущем процессе/потоке.
Здравствуйте, finist_, Вы писали:
ГМ>>>>Если я не ошибаюсь, Windows имеет только один TSS для всех процессов (вообще-то там еще есть другие TSS, но они связаны с выполнением нормального кода). Это означает, что пользоваться битами L0...L3 регистра DR7 не получится. ГМ>>Здесь моя опечатка — следует читать "но они не связаны с выполнением нормального кода".
_>-- _>Простите мою непонятливость, но вот что мне пришло в голову: TSS — Task-State Segment. По-русски, контекст процесса, вроде. Да, конечно, в процессоре место под него одно. Но ведь у каждого процесса свой контекст? Потому и есть понятие "смена контекста" — когда переключаются процессы, состояния регистров старого процесса виндой должно куда-то записываться, а потом извлекаться обратно, когда процесс сможет продолжить выполнение. Таким образом, мне стало совсем непонятно, как может котекст процесса (TSS) быть не связан с выполнением "нормального кода".
--
Нет, я не это имел ввиду. В Windows есть TSS, связанный с выполнением нормального кода. Но, если я не ошибаюсь, при переключении процессов он остается неизменным.
Однако ведь TSS нужен не только для исполнения кода процессов, но может использоваться и при обработке прерываний и исключений — именно это я и подразумевал, когда говорил, что эти TSS'ы не связаны с выполнением нормального кода.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Нет, я не это имел ввиду. В Windows есть TSS, связанный с выполнением нормального кода. Но, если я не ошибаюсь, при переключении процессов он остается неизменным.
--
Он не может оставаться неизменным. Допустим, один процесс записал в AX единицу, потом поработал второй процесс, записал в AX двойку, потом работает опять первый процесс. Что будет в AX? Должна быть единица, на мой взгляд. Но раз так, то регистр должен был сохраняться и восстанавливаться.
ГМ>Однако ведь TSS нужен не только для исполнения кода процессов, но может использоваться и при обработке прерываний и исключений — именно это я и подразумевал, когда говорил, что эти TSS'ы не связаны с выполнением нормального кода.
--
А при обработке прерываний (за все не скажу, но те, которые обрабатывает драйвер в режиме ядра, точно) TSS не заводится новый при выполнении обработчика — он выполняется в TSS последнего выполнявшегося процесса. Так написано в msdn.
Т.е. если бы срабатывал watchpoint при обработке прерывания, возникшего, когда работал мой отлаживаемый процесс — я бы понял. Но watchpoint'ы срабатывают в совершенно посторонних полноценный процессах: IE, Photoshop, Far...
ГМ>Можно, наверное, запомнить информацию о процессе/потоке перед установкой watchpoint и затем, при ее срабатывании, дополнительно сравнивать ее с информацией о текущем процессе/потоке.
--
Интересная идея, спасибо... Боюсь только, что это сравнение может прилично приуменьшить ускорение от использования аппаратных watchpoint'ов, но это нужно проверить. Вы не подскажете, как повесить обработчик прерывания переключения процессов? На свой процесс я умею вешать — просто выставляешь регистры, а потом ловишь прерывание в __except блоке. А чужие переключения как отлавливать? Особенно тот момент, когда вновь включается отлаживаемый процесс в работу...
ГМ>>Можно, наверное, запомнить информацию о процессе/потоке перед установкой watchpoint и затем, при ее срабатывании, дополнительно сравнивать ее с информацией о текущем процессе/потоке.
_>-- _>Интересная идея, спасибо... Боюсь только, что это сравнение может прилично приуменьшить ускорение от использования аппаратных watchpoint'ов, но это нужно проверить.
--
Насколько я понял, для того, чтобы останавливаться в заданном потоке, достаточно только запомнить и сравнивать содержимое регистра FS. Если нужно останавливаться для всех потоков процесса, то из этого thread information block наверняка можно быстро получить информацию и идентификатооре процесса (но у меня нет сейчас под руками соответствующей информации, чтобы это проверить).
Вы не подскажете, как повесить обработчик прерывания переключения процессов? На свой процесс я умею вешать — просто выставляешь регистры, а потом ловишь прерывание в __except блоке. А чужие переключения как отлавливать? Особенно тот момент, когда вновь включается отлаживаемый процесс в работу...
--
Увы, не подскажу.
Здравствуйте, finist_, Вы писали:
ГМ>>Нет, я не это имел ввиду. В Windows есть TSS, связанный с выполнением нормального кода. Но, если я не ошибаюсь, при переключении процессов он остается неизменным. _>-- _>Он не может оставаться неизменным. Допустим, один процесс записал в AX единицу, потом поработал второй процесс, записал в AX двойку, потом работает опять первый процесс. Что будет в AX? Должна быть единица, на мой взгляд. Но раз так, то регистр должен был сохраняться и восстанавливаться.
--
Наверное, вместо "процесс" подразумевался "поток", нет?
Если имеется ввиду, что содержимое TSS меняется потому, что в нем, например, сохраняются регистры при переключении потоков, то, это, скорее всего не так. Насколько я понял из "Inside Microsoft Windows 2000", при переключении потоков содержимое регистров, указателей на стеки и другая информация о процессе/потоке сохраняется в kernel mode стеке того потока, который "теряет" управление, а указатель стека сохраняется в структуре KTHREAD этого потока. Затем, когда поток вновь получит управление, контекст работы потока может быть быть легко восстановлен.
ГМ>>Однако ведь TSS нужен не только для исполнения кода процессов, но может использоваться и при обработке прерываний и исключений — именно это я и подразумевал, когда говорил, что эти TSS'ы не связаны с выполнением нормального кода. _>-- _>А при обработке прерываний (за все не скажу, но те, которые обрабатывает драйвер в режиме ядра, точно) TSS не заводится новый при выполнении обработчика — он выполняется в TSS последнего выполнявшегося процесса. Так написано в msdn.
--
Я не имел ввиду обработчики "нормальных" прерываний.
В таблице IDT есть несколько точек входа для обработки аварийный ситуаций (например, double fault exception). Если я не ошибаюсь, то как раз для них и используется Task Gate с отдельным TSS для того, чтобы Windows могла "успешно" :) аварийно завершится в BSOD.
Здравствуйте, finist_, Вы писали:
_>Здравствуйте, Геннадий Майко, Вы писали:
ГМ>>Нет, я не это имел ввиду. В Windows есть TSS, связанный с выполнением нормального кода. Но, если я не ошибаюсь, при переключении процессов он остается неизменным. _>-- _>Он не может оставаться неизменным. Допустим, один процесс записал в AX единицу, потом поработал второй процесс, записал в AX двойку, потом работает опять первый процесс. Что будет в AX? Должна быть единица, на мой взгляд. Но раз так, то регистр должен был сохраняться и восстанавливаться.
Ну безусловно такое должно выполняться в любой многозадачной среде, но тут просто вопрос в другом, а именно как это реализовано? В процессорах Интел есть аппаратная поддержка TSS, но по некоторым причинам в виндовсе полностью все возможности этого не используются(уж почему так я не знаю), т.е. каждый процесс работает с одной и тойже копией TSS. Указатель на дескриптор всегда один и тот же(это который TR).
ЗЫ: В какой то книге читал про обяснения причин почему МС сделала именно так, но сейчас не помню даже в какой, не говоря о самих причинах. Хотя при полной использовании аппаратного TSS переключение происходила бы быстрее(опять же идея из того же источника).
ГМ>>Однако ведь TSS нужен не только для исполнения кода процессов, но может использоваться и при обработке прерываний и исключений — именно это я и подразумевал, когда говорил, что эти TSS'ы не связаны с выполнением нормального кода. _>-- _>А при обработке прерываний (за все не скажу, но те, которые обрабатывает драйвер в режиме ядра, точно) TSS не заводится новый при выполнении обработчика — он выполняется в TSS последнего выполнявшегося процесса. Так написано в msdn. _>Т.е. если бы срабатывал watchpoint при обработке прерывания, возникшего, когда работал мой отлаживаемый процесс — я бы понял. Но watchpoint'ы срабатывают в совершенно посторонних полноценный процессах: IE, Photoshop, Far...
Большое спасибо за ответы!
Придётся теперь учиться вешать обработчик прерывания на переключение процессов...
и копаться в свободных отладчиках — может, кто-нибудь реализовал аппаратную поддержку...
Здравствуйте, finist_, Вы писали:
_>Большое спасибо за ответы! _>Придётся теперь учиться вешать обработчик прерывания на переключение процессов... _>и копаться в свободных отладчиках — может, кто-нибудь реализовал аппаратную поддержку...
_>
_>С уважением, _>Константин.
добрый день!
если мне не изменяет память, то по отладочным регистрам можно поставить не более 4(четырех) точек (при этом в каждом thread'е они свои и причем тут TSS я не понял). в нормальных отладчиках можно ставить гораздо больше.
точки по выполнению все-таки лучше делать вставляя 0xCC в код, точки по доступу/записи можно сделать устанавливая права на страницу и "фильтруя базар". практически в обычных приложениях скорость уменьшается незначительно.
попытки установить отладочные регистры, кстати, в W2k не увенчались успехом. при выходе из отладочного события они устанавливаются как система пожелает.
---
С уважением,
Сергей Мухин
D>ЗЫ: В какой то книге читал про обяснения причин почему МС сделала именно так, но сейчас не помню даже в какой, не говоря о самих причинах. Хотя при полной использовании аппаратного TSS переключение происходила бы быстрее(опять же идея из того же источника).
Объяснение простое — аппаратная поддержка переключения задач в Интеле медленне, чем его программный аналог. Это инфа от самого Интела.
Кстати насколько я понимаю большинство(а возможно и все) юниксы на x86 тоже не используют данный механизм.
И еще TSS — это Интеловский Task State Segment, в Виндах используется CONTEXT структура для хранения состояния регистров потока (включает и дебаг регистры).