воскресенье, 10 апреля 2011 г.

Отладка STL контейнера map в WinDbg

Проблема

Довольно часто во время отладки или анализа креш-дампов требуется узнать содержимое контейнера map. Насколько мне известно, WinDbg для этого не предоставляет никаких средств.

Решение

Решить задачу можно несколькими способами:
  • Зная внутреннюю структуру контейнера вручную найти необходимые смещения структур в памяти;
  • Создать своё расширение отладчика;
  • Воспользоваться возможностями расширения pykd.

Мною был выбран последний способ, поскольку, он имеет следующие преимущества:
  • Относительно низкий порог вхождения. Для создания скриптов вполне достаточно ознакомиться с синтаксисом языка Python, pykd API и примерами;
  • Высокая скорость разработки;
  • Несравнимо удобный синтаксис языка Python по сравнению с синтаксисом скриптового движка WinDbg;
  • Возможность отладки скриптов.

Буквально за вечер был создан скрипт позволяющий распечатывать содержимое контейнера. Его последнюю версию можно взять в репозитории проекта или же установив новейшую версию расширения pykd с помощью инсталлятора.

Использование

В качестве примера рассмотрим определённый следующим образом контейнер:
struct CSome
{
    int Field1;
    char Field2;
};

typedef std::map<int, CSome*> CSomeMap;

CSomeMap someMapName;
Распечатать содержимое структуры CSome можно так:
0:000:x86> .foreach ( x  {!py stlp map someMapName}) { .block {.echo "------------------------------"}; dt CSome poi(${x} + 0x4) }

------------------------------
StlportMapTest!CSome
   +0x000 Field1           : 0n100
   +0x004 Field2           : 65 'A'
------------------------------
StlportMapTest!CSome
   +0x000 Field1           : 0n200
   +0x004 Field2           : 66 'B'
------------------------------
StlportMapTest!CSome
   +0x000 Field1           : 0n300
   +0x004 Field2           : 67 'C'
Следующим образом можно вывести ключ и значение:
0:000:x86> .foreach ( x  {!py stlp map someMapName}) { .block {.echo "------------------------------"}; dt -r StlportMapTest!stlp_std::pair<int const ,CSome *> x }

------------------------------
   +0x000 first            : 0n0
   +0x004 second           : 0x00956d20 CSome
      +0x000 Field1           : 0n100
      +0x004 Field2           : 65 'A'
------------------------------
   +0x000 first            : 0n1
   +0x004 second           : 0x00956dc0 CSome
      +0x000 Field1           : 0n200
      +0x004 Field2           : 66 'B'
------------------------------
   +0x000 first            : 0n2
   +0x004 second           : 0x00956e60 CSome
      +0x000 Field1           : 0n300
      +0x004 Field2           : 67 'C'
А так же, можно вывести ключ и значение с помощью самого скрипта указав в качестве параметра соответствующий тип:
0:000:x86> !py stlp map someMapName "StlportMapTest!stlp_std::pair<int const ,CSome *>"

------------------------------------------------
   +0x000 first            : 0n0
   +0x004 second           : 0x00956d20 CSome
      +0x000 Field1           : 0n100
      +0x004 Field2           : 65 'A'
------------------------------------------------
   +0x000 first            : 0n1
   +0x004 second           : 0x00956dc0 CSome
      +0x000 Field1           : 0n200
      +0x004 Field2           : 66 'B'
------------------------------------------------
   +0x000 first            : 0n2
   +0x004 second           : 0x00956e60 CSome
      +0x000 Field1           : 0n300
      +0x004 Field2           : 67 'C'
При печати полного содержимого карты следует обратить внимание на точное соответствие типа, вплоть до каждого отступа. Для этого можно воспользоваться командой dt:
0:000:x86> dt StlportMapTest!stlp_std::pair<*

          StlportMapTest!stlp_std::pair<int const ,int>
          .......
нужный -> StlportMapTest!stlp_std::pair<int const ,CSome *>
          .......

В данный момент скрипт поддерживает реализацию контейнера map из библиотеки STLPort. Корректно работает на платформах x86 и x64.
Пожелания, предложения, ошибки или недочёты можно оставлять в комментариях или создать соответствующий Work Item на странице проекта pykd.

Рабочая среда: WinDbg 6.12.0002.633, pykd 0.0.0.16, STLPort 5.2

Комментариев нет:

Отправить комментарий