Time Travel Debugging в новом WinDbg +47


Возможно, вы уже слышали о том, что Microsoft выпустила обновлённую версию своего известного отладчика WinDbg, который и раньше был хорош, но слишком уж отстал по интерфейсу от современных тенденций. Новая версия WinDbg, к счастью, не пошла настолько далеко, чтобы получить новомодный UWP-интерфейс, но вот классические риббон-бары в стиле Microsoft Office — ей очень идут. Приложение распространяется только через Microsoft Store и работают на Win10 как минимум с Anniversary Update. Microsoft говорит, что это сделано для удобства установки и обновления, но я как-то не помню, чтобы с классическим WinDbg были какие-то проблемы с установкой. Скорее это выглядит как ещё один способ приучения разработчиков и пользователей к привычке пользоваться только самой последней версией Windows. Ну ок, пусть так.

WinDbg выглядит симпатично:

image

И вся его мощь в виде команд, отладки драйверов, удалённой отладки, скриптов и прочего — осталась при нём. Более того, 25 сентября было выпущено обновление, добавляющее в новый WinDbg важную фичу — отладку с возможностью двигаться по ходу работы программы в обратном направлении (Time Travel Debugging). Возможность интересная, поскольку попав в некоторое невалидное состояние программист часто задаётся вопросом «А как же так вышло?». Ранее получить на него ответ можно было либо проигрывая в уме команды в обратном порядке, либо перезапуская отладку снова и снова с добавлением логов и новых контрольных точек. Всё это занимало время. Давайте посмотрим, как это работает сейчас.

Устанавливаем WinDbg

Пишем каку-нибудь небольшую программу и компилируем её. Я взял первую попавшуюся в Интернете реализацию пузырьковой сортировки (да, потому, что я лентяй).

Пузырьковая сортировка
#include "stdafx.h"

void swap(int *xp, int *yp)
{
	int temp = *xp;
	*xp = *yp;
	*yp = temp;
}

// An optimized version of Bubble Sort
void bubbleSort(int arr[], int n)
{
	int i, j;
	bool swapped;
	for (i = 0; i < n - 1; i++)
	{
		swapped = false;
		for (j = 0; j < n - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				swap(&arr[j], &arr[j + 1]);
				swapped = true;
			}
		}

		// IF no two elements were swapped by inner loop, then break
		if (swapped == false)
			break;
	}
}

/* Function to print an array */
void printArray(int arr[], int size)
{
	int i;
	for (i = 0; i < size; i++)
		printf("%d ", arr[i]);
}

// Driver program to test above functions
int main()
{
	int arr[] = { 64, 34, 25, 12, 22, 11, 90 };
	int n = sizeof(arr) / sizeof(arr[0]);
	bubbleSort(arr, n);
	printf("Sorted array: \n");
	printArray(arr, n);
	return 0;
}


Теперь у нас есть скомпилированный бинарник, символьный файл к нему и файл с исходником. Это всё понадобится для WinDbg.

Запускаем WinDbg с привилигиями администратора (это важно!). Выбираем File > Start debugging > Launch executable (advanced):



Задаём путь к отлаживаемому бинарнику, ставим галку «Record process with Time Travel Debugging», задаём путь для сохранения записанного трейса выполнения.



Жмём ок, программа запускается, отрабатывает и закрывается. WinDbg сохраняет записанный трейс выполнения в указанную папку и сразу же загружает его (это экономит время отладки).



Теперь открываем в WinDbg файл с кодом, ставим пару брейкпоинтов, запускаем отладку. На первый взгляд всё выглядит знакомо.



Но вот оно — главное отличие:



Нам доступен блок реверсивного управления направлением выполнения кода. Мы можем просто ступить на строку назад.



Мы можем поставить новый брейкпоинт где-нибудь выше и нажать «Go back», чтобы обратное выполнение программы дошло до него.



Обратите внимание — мы прыгнули назад во времени до входа программы в циклы for — и вот внизу в окне Locals мы уже видим, что переменные i и j в этот момент ещё имеют неопределённые значения.

Мы можем ходить вперёд и назад сколько угодно, перезапускать отладку с самого начала. Можно коннектится к уже запущенным процессам для записи выполнения только определённых блоков кода. Очень удобно ловить баги, которые воспроизводятся только иногда или только в определённом окружении, а потом прокручивать их снова и снова.

В общем, фича мне нравится.

Материалы по теме:

  1. Анонс фичи в блоге WinDbg
  2. Документация
  3. Установить WinDbg




К сожалению, не доступен сервер mySQL