Home > itblogs > Расширение для WinDbg: «Outline».

Расширение для WinDbg: «Outline».

May 16th, 2009

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

На данный момент реализована только одна команда «!fnframe». Она показывает структуру стекового фрейма для произвольной функции: локальные переменные и параметры, сохраненные регистры, указатель фрейма. На x64 помимо символов используется сгенерированная компилятором unwind information, что обеспечивает большую достоверность результатов. Поддержка Itanium пока в планах.

Скачать:

Примеры:

x86 сборка Far Manager 2.0 с включенным frame pointer omission:

0:000:x86> .load outline
0:000:x86> !fnframe far!wmain
 Start of frame               --> -0x78
   -0x78   Saved registers      : 0x10 bytes
   -0x64   strViewName          : class UnicodeString, 0x4 bytes
   -0x60   strEditName          : class UnicodeString, 0x4 bytes
   -0x5c   StartLine            : int, 0x4 bytes
   -0x58   CntDestName          : int, 0x4 bytes
   -0x54   DestNames            : class UnicodeString [2], 0x8 bytes
   -0x4c   RectoreConsole       : int, 0x4 bytes
   -0x48   StartChar            : int, 0x4 bytes
   -0x44   __ConsoleRestore     : class TConsoleRestore, 0x24 bytes
   -0x20   buf                  : char [15], 0xf bytes
   +0x0    Return address       : 0x4 bytes
   +0x4    Argc                 : int, 0x4 bytes
   +0x8    Argv                 : wchar_t **, 0x4 bytes
 End of frame                 --> +0xc
0:000:x86>

x64 сборка того же Far Manager 2.0:

0:000> !fnframe far!wmain
 Start of frame               --> +0x0
   +0x0    rcx home             : 0x8 bytes
   +0x8    rdx home             : 0x8 bytes
   +0x10   r8 home              : 0x8 bytes
   +0x18   r9 home              : 0x8 bytes
   +0x40   strEditName          : class UnicodeString, 0x8 bytes
   +0x48   strViewName          : class UnicodeString, 0x8 bytes
   +0x50   DestNames            : class UnicodeString [2], 0x10 bytes
   +0x60   __ConsoleRestore     : class TConsoleRestore, 0x30 bytes
   +0x98   buf                  : char [15], 0xf bytes
   +0xb0   r15                  : 0x8 bytes
   +0xb8   r14                  : 0x8 bytes
   +0xc0   r13                  : 0x8 bytes
   +0xc8   r12                  : 0x8 bytes
   +0xd0   rdi                  : 0x8 bytes
   +0xd8   rsi                  : 0x8 bytes
   +0xe0   rbp                  : 0x8 bytes
   +0xe8   Return address       : 0x8 bytes
 End of frame                 --> +0xf0
   +0xf0   Argc                 : int, 0x4 bytes
   +0xf8   Argv                 : wchar_t **, 0x8 bytes
   +0x100  rbx                  : 0x8 bytes
0:000>

Публичные символы не описывают ntdll!KiUserExceptionDispatcher (точка входа диспетчера исключений пользовательского режима), но включенная в бинарный файл unwind information дает кое-какое представление об этой функции:

0:000> !fnframe ntdll!KiUserExceptionDispatcher
 Start of frame               --> +0x0
   +0x0    rcx home             : 0x8 bytes
   +0x8    rdx home             : 0x8 bytes
   +0x10   r8 home              : 0x8 bytes
   +0x18   r9 home              : 0x8 bytes
   +0x90   rbx                  : 0x8 bytes
   +0xa0   rbp                  : 0x8 bytes
   +0xa8   rsi                  : 0x8 bytes
   +0xb0   rdi                  : 0x8 bytes
   +0xd8   r12                  : 0x8 bytes
   +0xe0   r13                  : 0x8 bytes
   +0xe8   r14                  : 0x8 bytes
   +0xf0   r15                  : 0x8 bytes
   +0x200  xmm6                 : 0x10 bytes
   +0x210  xmm7                 : 0x10 bytes
   +0x220  xmm8                 : 0x10 bytes
   +0x230  xmm9                 : 0x10 bytes
   +0x240  xmm10                : 0x10 bytes
   +0x250  xmm11                : 0x10 bytes
   +0x260  xmm12                : 0x10 bytes
   +0x270  xmm13                : 0x10 bytes
   +0x280  xmm14                : 0x10 bytes
   +0x290  xmm15                : 0x10 bytes
   +0x590  Machine frame        : 0x28 bytes
 End of frame                 --> +0x5b8
0:000>
  1. MaD
    May 17th, 2009 at 11:35 | #1

    Хым, то, чего действительно не хватало. Работает как положено :)

  2. byleas
    May 18th, 2009 at 02:41 | #2

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

    Что-то подобное мне нужно прикрутить к IDA, т.к. сейчас занимаюсь как раз проблемами реализации поддержки исключений С++ для х64 (eh.lib не предлагать, мне нужно для KM).

  3. byleas
    May 18th, 2009 at 02:42 | #3

    Странно, “Sorry, but your comment has been flagged by the spam filter running on this blog: this might be an error, in which case all apologies.” постоянно..

    • May 18th, 2009 at 05:51 | #4

      Странно, “Sorry, but your comment has been flagged by the spam filter running on this blog: this might be an error, in which case all apologies.” постоянно..

      Это вот почему:

      Spam vs. not spam

  4. May 18th, 2009 at 06:10 | #5

    byleas :
    Интересно. А нельзя ли озвучить, на основе чего сделано расширение? Или исходный код посмотреть.

    IDebugSymbols::GetScopeSymbolGroup и IDebugSymbols3::GetFunctionEntryByOffset. Плюс немного черной магии для разбора unwind information. Исходники, наверное, выложу со временем.

Comments are closed.