Windbg - можно! For_each_frame подражать .for, .do или. While? - PullRequest
0 голосов
/ 20 сентября 2018

!for_each_frame будет перебирать каждый кадр потока и позволять вам запускать команды (даже несколько команд) в одной строке.

Есть ли способ сделать простой цикл всценарий Windbg, чтобы вы могли начать с кадра 00 текущего потока, выполнить итерацию до последнего кадра и делать все, что вы хотите сделать в каждом кадре в рамках хорошего многострочного многоэтапного блока кода?

Этот код, очевидно, будет повторяться, но он никогда не остановится, пока вы не выполните отладку.Это верно даже в том случае, если Windbg начинает сообщать Cannot find frame 0xXX, previous scope unchanged, так как я могу быть в состоянии проверить необходимое мне условие?

.frame 0n0
.do
{
  .f+
}
(1==1)

Есть ли что-то, что я могу получить и сохранить до начала .do,или какой-то встроенный токен потока, который я могу проверить в Условии, или какое-то условие ошибки, которое будет затронуто .f+, когда оно переходит к более высоким кадрам, на которое я могу просто выпрыгнуть?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018
0:000> dx @$curstack.Frames.Count()
@$curstack.Frames.Count() : 0x4
0:000> .cxr;r $t0 = 0;.do { .f+ ; r $t0 = @$t0+1 } (@$t0 < 4 )
Resetting default scope
01 0014fa14 770060a7 ntdll!LdrpInitializeProcess+0x11a9
02 0014fa64 77003659 ntdll!_LdrpInitialize+0x78
03 0014fa74 00000000 ntdll!LdrInitializeThunk+0x10
Cannot find frame 0x4, previous scope unchanged
03 0014fa74 00000000 ntdll!LdrInitializeThunk+0x10

На основании комментария Уильяма Мессмера вы можете назначить выражение dx примитивному псевдорегистру при условии, что вы используете его как dx

Мой предыдущий комментарий о том, что вы не можете назначить, был основан на этом формате, которыйне работает

.for( r $t0 = @$curstack.Frames.Count() ;......)

, но здесь есть ошибка

, которую вы можете использовать

**dx @$t0 = @$curstack.Frames.Count()** and use the Pseudo Register inside any loop variables 

псевдорегистру, которому присвоено значение, не приводит кошибка

хотя это похоже на создание пользовательской переменной
вроде dx @ $ foo = @ $ curStack.Frames.Count ()

, похожемы не можем использовать @ $ foo в качестве переменной цикла

. Вот простой документ, основанный на тестах

C:> cdb cdb
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86

0: 000> dx @ $ t1 = @ $ curstack.Frames.Count ()

@$t1 = @$curstack.Frames.Count() : 0x4 [Type: unsigned __int64]

0:000> .for (dx @ $ t0 = 0; @ $ t0 <@ $ t1; r $ t0 = @ $ t0 +1) {.frame @ $ t0} </strong>

@$t0 =0          : 0 [Type: int]
00 0012fad0 77000e00 ntdll!LdrpDoDebuggerBreak+0x2c
01 0012fc30 76fe60a7 ntdll!LdrpInitializeProcess+0x11a9
02 0012fc80 76fe3659 ntdll!_LdrpInitialize+0x78
03 0012fc90 00000000 ntdll!LdrInitializeThunk+0x10

0: 000> .cxr;dx @ $ t0 = 0; .do {.f +;r $ t0 = @ $ t0 + 1} (@ $ t0 <@ $ t1) </strong>

Resetting default scope
@$t0 =0          : 0 [Type: int]
01 0012fc30 76fe60a7 ntdll!LdrpInitializeProcess+0x11a9
02 0012fc80 76fe3659 ntdll!_LdrpInitialize+0x78
03 0012fc90 00000000 ntdll!LdrInitializeThunk+0x10
Cannot find frame 0x4, previous scope unchanged
03 0012fc90 00000000 ntdll!LdrInitializeThunk+0x10
0:000>

0: 001> .for (dx @ $ t0 = 0; @ $t0 <@ $ t1; r $ t0 = @ $ t0 +1) {.echo "hi";??(@ $ t0 * 3.1415)} </strong>

@$t0 =0          : 0 [Type: int]
hi
double 0
hi
double 3.1415000000000001812
hi
double 6.2830000000000003624
hi
double 9.4245000000000000995
hi
double 12.566000000000000725
hi
double 15.70750000000000135
hi
double 18.849000000000000199
hi
double 21.990500000000000824
hi
double 25.13200000000000145
hi
double 28.273500000000002075
hi
double 31.4150000000000027
0:001>

нужен c ++, а не masm для оценки с помощью?из-за синтаксической ошибки

ошибка константы c ++, похоже, оценивается

** 0: 001> .expr
Текущий оценщик выражений: MASM - выражения Microsoft Assembler

0: 001> .for (dx @ $ t0 = 0; @ $ t0 <@ $ t1; r $ t0 = @ $ t0 +1) {.echo "hi";?(@ $ t0 * 3.1415)} **</p>

@$t0 =0          : 0 [Type: int]
hi
Syntax error at '3.1415 ) '

0: 001> .for (dx @ $ t0 = 0; @ $ t0 <@ $ t1; r $ t0 = @ $t0 +1) {.echo "hi";?(@ $ t0 * @@ c ++ (3.1415))} </strong>

@$t0 =0          : 0 [Type: int]
hi
Evaluate expression: 0 = 00000000
hi
Evaluate expression: 3 = 00000003
hi
Evaluate expression: 6 = 00000006
hi
Evaluate expression: 9 = 00000009
hi
Evaluate expression: 12 = 0000000c
hi
Evaluate expression: 15 = 0000000f
hi
Evaluate expression: 18 = 00000012
hi
Evaluate expression: 21 = 00000015
hi
Evaluate expression: 24 = 00000018
hi
Evaluate expression: 27 = 0000001b
hi
Evaluate expression: 30 = 0000001e
0 голосов
/ 20 сентября 2018

Для таких задач, как это, я бы посоветовал вам взглянуть на встроенную поддержку JavaScript (особенно в WinDbg Preview).В целом, это значительно облегчает выполнение таких задач, как «командный / точечный сценарий», который долгое время находился в отладчике.Приведенный ниже скрипт демонстрирует пример этого:

"use strict";

function invokeScript()
{
    for (var frame of host.currentThread.Stack.Frames)
    {
        // Do whatever you want:
        host.diagnostics.debugLog("I just found frame: ", frame, "\n");
    }
}

Вы можете запустить этот скрипт в WinDbg Preview, просто нажав кнопку «выполнить» на ленте ... или поместив его в файл и ".scriptrunFullScriptPath.js ".

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

...