WinDbg: временные шкалы

логотип WinDbg с увеличивающимся стеклом, проверяющим биты.

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

Снимок экрана: временная шкала в отладчике с исключениями, доступом к памяти, точками останова и вызовами функций.

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

Окно временной шкалы отображается при открытии файла трассировки TTD. В нем отображаются ключевые события без необходимости вручную создавать запросы модели данных. В то же время все объекты перемещения по времени доступны, чтобы обеспечить более сложные запросы данных.

Дополнительные сведения о создании и работе с файлами трассировки перемещения по времени см. в разделе "Отладка временных путешествий : обзор".

Типы временных шкал

В окне "Временная шкала" отображаются события в следующих временных шкалах:

  • Исключения. Вы можете отфильтровать определенный код исключений.
  • Точки останова: можно увидеть, когда точки останова попадают на временную шкалу.
  • Доступ к памяти: можно считывать, записывать и выполнять между двумя адресами памяти.
  • Вызовы функций: можно выполнять поиск в виде module!function.

Наведите указатель мыши на каждое событие, чтобы получить дополнительные сведения с помощью подсказки. При выборе события выполняется запрос события и отображаются дополнительные сведения. Когда пользователь дважды щелкает на событии, файл трассировки TTD переходит в это расположение.

Исключения

При загрузке файла трассировки и при активной временной шкале автоматически отображаются все исключения в записи.

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

Снимок экрана: временная шкала в отладчике, отображающая исключения с информацией о конкретном коде исключения.

Можно дополнительно отфильтровать определенный код исключения с помощью необязательного поля "Код исключения ".

Снимок экрана диалогового окна исключения в отладчике временной шкалы: тип шкалы установлен на

Можно также добавить новую временную шкалу для определенного типа исключения.

Точки останова

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

Снимок экрана: временная шкала в отладчике, отображающая примерно 30 индикаторов точек останова.

После очистки точки останова связанная временная шкала точек останова автоматически удаляется.

Вызовы функций

На временной шкале отображаются позиции вызовов функций. Чтобы выполнить этот шаг, укажите поиск в виде module!function. Примером является TimelineTestCode!multiplyTwo. Можно также указать подстановочные знаки, например TimelineTestCode!m*.

Снимок экрана: добавление временной шкалы в отладчик с введенным именем вызова функции.

При наведении указателя мыши на вызов функции имя функции, входные параметры, их значения и возвращаемое значение отображаются. В этом примере показаны буфер и размер, поскольку они являются параметрами для DisplayGreeting!GetCppConGreeting.

Снимок экрана: временная шкала в отладчике с вызовами функций и окном

Обращение к памяти

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

Снимок экрана: добавление диалогового окна

При наведении указателя мыши на элемент доступа к памяти появляется значение и указатель инструкции.

Снимок экрана: временная шкала в отладчике с событиями доступа к памяти.

Работа с временными шкалами

Вертикальная серая линия перемещается вместе с курсором, когда вы наводите его на временную шкалу. Вертикальная синяя линия указывает текущую позицию трассировки.

Выберите значки с изображением лупы, чтобы увеличить или уменьшить масштаб на временной шкале.

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

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

Движения мыши

Чтобы увеличить и уменьшить масштаб, нажмите клавиши CTRL и используйте колесико прокрутки.

Чтобы сдвинуть с стороны на сторону, выберите shift и используйте колесико прокрутки.

Методы отладки временной шкалы

Чтобы продемонстрировать методы отладки временной шкалы, здесь повторно используется руководство по отладке с путешествием во времени. В этой демонстрации предполагается, что вы завершили первые два шага для создания примера кода и создали запись TTD с помощью первых двух описанных здесь шагов.

В этом сценарии первым шагом является поиск исключения в трассировке перемещения по времени. Дважды щелкните единственное исключение, которое отображается на временной шкале.

В окне командной строки вы увидите, что при выборе исключения была выдана следующая команда.

(2dcc.6600): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: CC:0
@$curprocess.TTD.Events.Where(t => t.Type == "Exception")[0x0].Position.SeekTo()

Выберите "Просмотреть>регистры" , чтобы отобразить регистры на этой точке временной шкалы, чтобы начать исследование.

Снимок экрана: временная шкала в отладчике, отображающая исключение демонстрационной лаборатории и окно

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

По мере выполнения этого процесса изучите значения локальных переменных и стека:

  • Выберите "Просмотреть>локальные" для отображения локальных значений.
  • Выберите «Вид»>«Стек», чтобы отобразить стек выполнения кода.

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

На ленте "Главная " используйте команду "Шаг назад" , чтобы выполнить шаг назад три инструкции. По мере выполнения этого процесса продолжайте изучать окна Stack, Locals и Registers .

В окне Команды отображаются позиция путешествия во времени и регистры, когда вы возвращаетесь на три инструкции назад.

0:000> t-
Time Travel Position: CB:41
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00540020 esp=003cf7d0 ebp=00520055 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
00540020 ??              ???
0:000> t-
Time Travel Position: CB:40
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00061767 esp=003cf7cc ebp=00520055 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
DisplayGreeting!main+0x57:
00061767 c3              ret
0:000> t-
Time Travel Position: CB:3A
eax=0000004c ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=0006175f esp=003cf718 ebp=003cf7c8 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
DisplayGreeting!main+0x4f:
0006175f 33c0            xor     eax,eax

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

esp=003cf718 ebp=003cf7c8

Окно "Локальные" содержит значения из целевого приложения. В окне исходного кода выделена строка кода, готового к выполнению в исходном коде на этом этапе трассировки.

Чтобы провести дальнейшее исследование, откройте окно Память, чтобы просмотреть содержимое рядом с адресом памяти (указателем стекаesp). В этом примере имеется значение 003cf7c8. Выберите память>текст>ASCII, чтобы отобразить ASCII-текст, хранящийся по этому адресу.

Снимок экрана: отладчик, отображающий окна

Временная шкала доступа к памяти

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

Снимок экрана: диалоговое окно добавления диалогового окна доступа к памяти временной шкалы с выбранным параметром записи и начальным значением 003cf7c8.

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

Screenshot of memory access timeline and the Locals window displaying locals values with differing source and destination values. Screenshot of memory access timeline and the Locals window displaying locals values with differing source and destination values. Снимок экрана: шкала доступа к памяти и окно "Локальные переменные", в котором отображаются значения локальных переменных с различными исходными и конечными значениями.

Временная шкала точки останова

Использование точек останова — это распространенный подход для приостановки выполнения кода на каком-то событии, интересующем вас. С помощью TTD можно задать точку останова и вернуться назад до тех пор, пока эта точка останова не будет достигнута после записи трассировки. Возможность проверить состояние процесса после возникновения проблемы, чтобы определить оптимальное расположение точки останова, позволяет больше рабочих процессов отладки, уникальных для TTD.

Чтобы изучить альтернативный метод отладки временной шкалы, выберите исключение на временной шкале и еще раз выполните три шага назад с помощью команды "Шаг назад " на ленте "Главная ".

В этом маленьком примере легко просмотреть код. Если у вас есть сотни строк кода и десятки вложенных объектов, используйте описанные здесь методы, чтобы уменьшить время, необходимое для поиска проблемы.

Как упоминалось ранее, базовый указатель (esp) указывает на текст сообщения вместо указания инструкции.

ba Используйте команду, чтобы задать точку останова для доступа к памяти. Вы устанавливаете точку w - останова на запись, чтобы отслеживать, когда данные записываются в эту область памяти.

0:000> ba w4 003cf7c8

Хотя вы используете простую точку останова доступа к памяти, можно создать точки останова для более сложных условных операторов. Дополнительные сведения см. в разделе bp, bu, bm (Set Breakpoint).

В меню "Главная " выберите "Вернуться назад" до тех пор, пока точка останова не будет достигнута.

На этом этапе вы можете проверить стек программ, чтобы узнать, какой код активен.

Снимок экрана: временная шкала в отладчике с временной шкалой доступа к памяти и окнами стека.

Поскольку маловероятно, что предоставляемая корпорацией Майкрософт функция может иметь ошибку в коде, подобную этой, ищите дальше в стеке. Стек показывает, что Greeting!main вызывает Greeting!GetCppConGreeting. В небольшом примере кода вы можете открыть код на этом этапе и, скорее всего, найти ошибку легко. Но чтобы проиллюстрировать методы, которые можно использовать с более крупной, более сложной программой, вы добавите временную шкалу вызова функции.

Временная шкала вызова функции

Выберите +Добавить временную шкалу и заполните DisplayGreeting!GetCppConGreeting строку поиска функции.

Флажки "Начальное расположение " и "Конечное расположение " указывают начало и конец вызова функции в трассировке.

С помощью dx команды можно отобразить объект вызова функции, чтобы просмотреть связанные поля, TimeStart соответствующие TimeEnd начальному расположению и конечному расположению вызова функции.

dx @$cursession.TTD.Calls("DisplayGreeting!GetCppConGreeting")[0x0]
    EventType        : 0x0
    ThreadId         : 0x6600
    UniqueThreadId   : 0x2
    TimeStart        : 6D:BD [Time Travel]
    SystemTimeStart  : Thursday, October 31, 2019 23:36:05
    TimeEnd          : 6D:742 [Time Travel]
    SystemTimeEnd    : Thursday, October 31, 2019 23:36:05
    Function         : DisplayGreeting!GetCppConGreeting
    FunctionAddress  : 0x615a0
    ReturnAddress    : 0x61746
    Parameters  

Необходимо установить флажок «Начальное расположение» или «Конечное расположение», или оба флажка «Начальное расположение» и «Конечное расположение».

Снимок экрана: диалоговое окно

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

Снимок экрана: временная шкала в отладчике, отображающая временную шкалу доступа к памяти и окно

Изучение выполнения кода путем просмотра нескольких временных шкал

Хотя наш пример кода мал, метод использования нескольких временных шкал позволяет визуально исследовать трассировку перемещения по времени. Вы можете просмотреть файл трассировки, чтобы задать вопросы, такие как "Когда происходит обращение к области памяти до срабатывания точки останова?".

Снимок экрана временной шкалы в отладчике, отображающей временную шкалу обращений к памяти и окно Locals.

Возможность видеть больше корреляций и находить непредвиденные вещи отличает средство временной шкалы от взаимодействия с трассировкой перемещения во времени с помощью команд командной строки.

Закладки хронологии

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

Вы можете указать описательное имя для закладок.

Снимок экрана: диалоговое окно

Выберите Просмотр>Временная шкала, чтобы открыть окно временной шкалы и получить доступ к временной шкале закладок. При наведении указателя мыши на закладку появляется имя закладки.

Снимок экрана: временная шкала с тремя закладками с курсором, наведенным на одну, чтобы отобразить имя закладки.

Щелкните правой кнопкой мыши закладку, чтобы перейти к позиции закладки, переименовать закладку или удалить ее.

Снимок экрана: всплывающее меню

Замечание

Функция закладки недоступна в версии 1.2402.24001.0 WinDbg.