Поиск в стеке вызовов - PullRequest
       10

Поиск в стеке вызовов

0 голосов
/ 17 января 2019

Я анализирую дамп памяти и сбои многопоточных приложений C ++.

Как объяснено в этом вопросе VisualCommunity , меня интересуют все темы, которые не ждут и не спят.
В настоящее время я получаю этот ответ, используя Visual Studio (Threads окно):
1. копирование всех потоков на лист Excel (колонка 1),
2. скопировать отфильтрованные потоки «WaitFor» на лист Excel (колонка 2),
3. Скопируйте отфильтрованные потоки «Спящий режим» также на лист Excel (внизу столбца 2) и
4. используйте функцию рабочего листа Excel ± 1011 * для получения моих результатов (отфильтруйте эти результаты по #N/A).

Я хотел бы знать, могу ли я сделать что-то подобное (но проще) в Windbg.

В настоящее время я могу запросить полный список стеков вызовов (используя команду Windbg ~* kb).

Могу ли я сделать Search call stack в Windbg (скорее всего, добавив что-нибудь в команду ~* kb)? Существуют ли какие-либо расширенные возможности (например, регулярные выражения)?

Ответы [ 3 ]

0 голосов
/ 17 января 2019

команды должны быть в одной строке удалить разрыв строки в Where (), если вы копируете paste

0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where
( ( p=>p.ToDisplayString().Contains("Wait") == true ))

результат команды

@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).  
Where( ( p=>p.ToDisplayString().Contains("Wait") == true ))                
    [0x9dc]          : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
    [0x480]          : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
    [0xc4]           : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
    [0xae8]          : ntdll!NtWaitForSingleObject + 0xc [Switch To]
    [0xeac]          : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
    [0xf08]          : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
    [0xdd4]          : ntdll!NtWaitForSingleObject + 0xc [Switch To]
    [0xc64]          : ntdll!NtWaitForSingleObject + 0xc [Switch To]
    [0x89c]          : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    [0x162c]         : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]

команда для ложного условия снова должна быть однострочной

0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where  
( ( p=>p.ToDisplayString().Contains("Wait") == false ))

результат

@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]). 
Where( ( p=>p.ToDisplayString().Contains("Wait") == false ))                
    [0x208]          : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
    [0x3ec]          : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
    [0xadc]          : user32!NtUserGetMessage + 0xc [Switch To]
    [0x1794]         : ntdll!NtDelayExecution + 0xc [Switch To]
    [0xe78]          : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
    [0x1164]         : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]

сравнение вывода между! Busy из pde, как это было предложено командой Lieven, и встроенной командой, слегка измененной для исключения стеков "RemoveIo" и "Wait"

0:037> dx @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where(    
(p=>p.ToDisplayString().Contains("Wait") != true)).Where(p=>p.ToDisplayString().   
Contains("Remove") != true)

Результаты

@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).  
Where( (p=>p.ToDisplayString().Contains("Wait") !=   
true)).Where(p=>p.ToDisplayString().Contains("Remove") != true)                
    [0xd78]          : user32!NtUserGetMessage + 0xc [Switch To]
    [0xe44]          : user32!NtUserGetMessage + 0xc [Switch To]
    [0x514]          : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]
0:037> !busy

#  37 TID:0d78 kb kbn kbnL kn knL kpn kPn
 # ChildEBP RetAddr  
00 1737fdd8 770ccde0 ntdll!KiFastSystemCallRet
01 1737fddc 770cce13 user32!NtUserGetMessage+0xc
xxxx
0b 1737ff24 00000000 ntdll!_RtlUserThreadStart+0x1b

   50 TID:0e44 kb kbn kbnL kn knL kpn kPn
 # ChildEBP RetAddr  
00 1fb8fa18 770ccde0 ntdll!KiFastSystemCallRet
01 1fb8fa1c 770c18d9 user32!NtUserGetMessage+0xc
xxxxxx
07 1fb8fb20 00000000 ntdll!_RtlUserThreadStart+0x1b

   53 TID:0514 kb kbn kbnL kn knL kpn kPn
 # ChildEBP RetAddr  
00 144cf778 7780f20f ntdll!DbgBreakPoint
01 144cf7a8 7748ed6c ntdll!DbgUiRemoteBreakin+0x3c
xxxxxxx
05 144cf848 00000000 ntdll!_RtlUserThreadStart+0x1b

Threads: 3 of 54
Frames : 1
Command: knL
Mode   : Basic
0 голосов
/ 19 января 2019

Также есть команда !findstack. К сожалению, ему нужен символ в качестве параметра, поэтому подстановочные знаки или части имен не будут работать.

Пример:

0:001> !findstack wow64cpu!WaitForMultipleObjects32
Thread 001, 1 frame(s) match
        * 01 0000000006c0eb10 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b

Thread 003, 1 frame(s) match
        * 01 000000000bb3ebf0 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b
0 голосов
/ 17 января 2019

Расширение PDE от Эндрю Ричардса добавляет команду !busy

  !busy          - Equivalent of ~*knL but only displays stacks that are at least
                   'depth' frames deep (default depth is 1) and are not waiting for:-
                    ~ ntdll!NtWaitFor*
                    ~ ntdll!ZwWaitFor*
                    ~ ntdll!NtRemoveIoCompletion
                    ~ ntdll!ZwRemoveIoCompletion
                    ~ ntdll!NtReplyWaitReceivePort
                    ~ ntdll!ZwReplyWaitReceivePortEx

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

...