Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
U kunt JavaScript-automatisering gebruiken om op verschillende manieren met TTD-traceringen te werken, zoals opdrachtautomatisering of het gebruik van query's om gebeurtenisgegevens uit het traceringsbestand te vinden.
Zie JavaScript Debugger Scripting voor algemene informatie over het werken met JavaScript. Er zijn ook JavaScript-voorbeeldscripts voor foutopsporingsprogramma's.
JavaScript TTD-opdrachtautomatisering
Een manier om JavaScript te gebruiken voor TTD-automatisering, is door opdrachten te verzenden om het werken met tijdsreistraceringsbestanden te automatiseren.
Navigeren in een tracebestand
Dit JavaScript laat zien hoe u met de opdracht !tt naar het begin van een tijdreistracering gaat.
var dbgControl = host.namespace.Debugger.Utility.Control;
dbgControl.ExecuteCommand("!tt 0",false);
host.diagnostics.debugLog(">>> Sent command to move to the start of the TTD file \n");
We kunnen dit in een ResetTrace-functie maken en opslaan als MyTraceUtils.js, met behulp van de JavaScript-gebruikersinterface in WinDbg.
// My Trace Utils
// WinDbg TTD JavaScript MyTraceUtilsCmd Sample
"use strict";
function MyTraceUtilsCmd()
{
var dbgControl = host.namespace.Debugger.Utility.Control;
dbgControl.ExecuteCommand("!tt 0",false);
host.diagnostics.debugLog(">>> Sent command to move to the start of the TTD file \n");
}
Nadat een TTD-bestand in WinDbg is geladen, roept u de functie ResetTraceCmd() aan met behulp van de dx-opdracht in het opdrachtvenster voor foutopsporingsprogramma.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ResetTraceCmd()
>>> Sent command to move to the start of the TTD file
Debugger.State.Scripts.MyTraceUtils.Contents.ResetTraceCmd()
Beperkingen van het verzenden van opdrachten
Maar voor alle, maar de eenvoudigste situaties, heeft de benadering van het verzenden van opdrachten nadelen. Het is afhankelijk van het gebruik van tekstuitvoer. En het parseren van die uitvoer leidt tot code die broos en moeilijk te onderhouden is. Een betere benadering is om de TTD-objecten rechtstreeks te gebruiken.
In het volgende voorbeeld ziet u hoe u de objecten rechtstreeks kunt gebruiken om dezelfde taak rechtstreeks te voltooien met behulp van de objecten.
// My Trace Utils
// WinDbg TTD JavaScript ResetTrace Sample
"use strict";
function ResetTrace()
{
host.currentProcess.TTD.SetPosition(0);
host.diagnostics.debugLog(">>> Set position to the start of the TTD file \n");
}
Als u deze code uitvoert, ziet u dat we naar het begin van het traceringsbestand kunnen gaan.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ResetTrace()
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
>>> Set position to the start of the TTD file
In dit voorbeeld wordt de functie ResetTraceEnd ingesteld op het einde van de trace en wordt de huidige en nieuwe positie weergegeven met behulp van het object currentThread.TTD Position.
// WinDbg TTD JavaScript Sample to Reset Trace using objects directly
// and display current and new position
function ResetTraceEnd()
{
var PositionOutputStart = host.currentThread.TTD.Position;
host.diagnostics.debugLog(">>> Current position in trace file: "+ PositionOutputStart +"\n");
host.currentProcess.TTD.SetPosition(100);
var PositionOutputNew = host.currentThread.TTD.Position;
host.diagnostics.debugLog(">>> New position in trace file: "+ PositionOutputNew +"\n");
}
Als u deze code uitvoert, wordt de huidige en nieuwe positie weergegeven.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ResetTraceEnd()
>>> Current position in trace file: F:0
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: D3:1
>>> New position in trace file: D3:1
In dit uitgebreide voorbeeld worden de begin- en eindpositiewaarden vergeleken om te zien of de positie in de tracering is gewijzigd.
// WinDbg TTD JavaScript ResetTraceEx Sample
"use strict";
function ResetTraceEx()
{
const PositionOutputStart = host.currentThread.TTD.Position;
host.diagnostics.debugLog(">>> Current position in trace file: "+ PositionOutputStart +"\n");
host.currentProcess.TTD.SetPosition(0);
const PositionOutputNew = host.currentThread.TTD.Position;
host.diagnostics.debugLog(">>> New position in trace file: "+ PositionOutputNew +"\n");
if (parseInt(PositionOutputStart,16) != parseInt(PositionOutputNew,16))
{
host.diagnostics.debugLog(">>> Set position to the start of the TTD file \n");
}
else
{
host.diagnostics.debugLog(">>> Position was already set to the start of the TTD file \n");
}
}
In dit voorbeeld wordt een bericht weergegeven dat we allemaal klaar waren bij het begin van het traceerbestand.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ResetTraceEx()
>>> Current position in trace file: F:0
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
>>> New position in trace file: F:0
>>> Position was already set to the start of the TTD file
Als u het script wilt testen, gebruikt u de opdracht !tt om halverwege in het traceringsbestand te navigeren.
0:000> !tt 50
Setting position to 50% into the trace
Setting position: 71:0
Als u het script uitvoert, wordt nu het juiste bericht weergegeven dat aangeeft dat de positie is ingesteld op het begin van de TTD-trace.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ResetTraceEx()
>>> Current position in trace file: 71:0
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
>>> New position in trace file: F:0
>>> Set position to the start of the TTD file
Een traceringsbestand voor tijdreizen indexeren
Als alleen een traceringsbestand naar een andere pc wordt gekopieerd, moet het opnieuw worden geïndexeerd. Zie Time Travel Debugging - Werken met traceringsbestanden voor meer informatie.
Deze code toont een voorbeeld van een IndexTrace-functie die laat zien hoe lang het duurt om een traceringsbestand opnieuw te indexeren.
function IndexTrace()
{
var timeS = (new Date()).getTime();
var output = host.currentProcess.TTD.Index.ForceBuildIndex();
var timeE = (new Date()).getTime();
host.diagnostics.debugLog("\n>>> Trace was indexed in " + (timeE - timeS) + " ms\n");
}
Hier volgt de uitvoer van een klein traceringsbestand.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTrace()
>>> Trace was indexed in 2 ms
Een try catch-instructie toevoegen
Als u wilt controleren of er fouten zijn opgetreden tijdens het uitvoeren van de indexering, plaatst u de indexeringscode in een try catch-instructie.
function IndexTraceTry()
{
var timeS = (new Date()).getTime();
try
{
var IndexOutput = host.currentProcess.TTD.Index.ForceBuildIndex();
host.diagnostics.debugLog("\n>>> Index Return Value: " + IndexOutput + "\n");
var timeE = (new Date()).getTime();
host.diagnostics.debugLog("\n>>> Trace was successfully indexed in " + (timeE - timeS) + " ms\n");
}
catch(err)
{
host.diagnostics.debugLog("\n>>> Index Failed! \n");
host.diagnostics.debugLog("\n>>> Index Return Value: " + IndexOutput + "\n");
host.diagnostics.debugLog("\n>>> Returned error: " + err.name + "\n");
}
}
Hier volgt de scriptuitvoer als de indexering is geslaagd.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTraceTry()
>>> Index Return Value: Loaded
>>> Trace was successfully indexed in 1 ms
Als de tracering niet kan worden geïndexeerd, bijvoorbeeld als de tracering niet wordt geladen in het foutopsporingsprogramma, wordt de catch-luscode uitgevoerd.
0:007> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTraceTry()
>>> Index Failed!
>>> Index Return Value: undefined
>>> Returned error: TypeError
Queries voor JavaScript TTD-objecten
Een geavanceerder gebruik van JavaScript en TTD is om query's uit te voeren op de tijdreisobjecten om specifieke aanroepen of gebeurtenissen te vinden die in de trace zijn opgetreden. Zie voor meer informatie over de TTD-objecten:
Inleiding tot Time Travel Debugging-objecten
De dx-opdracht geeft informatie weer van het gegevensmodel voor foutopsporingsprogramma's en ondersteunt query's met behulp van LINQ-syntaxis. Dx is erg handig om query's uit te voeren op de objecten in realtime. Dit maakt het mogelijk om prototypen te maken van de gewenste query die vervolgens kan worden geautomatiseerd met behulp van JavaScript. De dx-opdracht biedt tabvoltooiing, wat handig kan zijn bij het verkennen van het objectmodel. Zie LINQ gebruiken met de foutopsporingsprogrammaobjecten voor algemene informatie over het werken met LINQ-query's en foutopsporingsprogrammaobjecten.
Met deze dx-opdracht worden alle aanroepen naar een bepaalde API geteld, in dit voorbeeld GetLastError.
0:000> dx @$cursession.TTD.Calls("kernelbase!GetLastError").Count()
@$cursession.TTD.Calls("kernelbase! GetLastError").Count() : 0x12
Met deze opdracht wordt in het hele tijdreisspoor gezocht om te zien wanneer GetLastError is aangeroepen.
0:000> dx @$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0)
@$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0)
[0x0]
[0x1]
[0x2]
[0x3]
Tekenreeksvergelijkingen voor TTD.Calls Object om oproepen te zoeken
In deze voorbeeldopdracht ziet u hoe u tekenreeksvergelijkingen gebruikt om specifieke aanroepen te vinden. In dit voorbeeld zoekt de query naar de tekenreeks OLE in de parameter lpFileName van de functie CreateFileW.
dx -r2 @$cursession.TTD.Calls("kernelbase!CreateFileW").Where(x => x.Parameters.lpFileName.ToDisplayString("su").Contains("OLE"))
Voeg een .Select-instructie toe om Timestart en de waarde van de lpFileName-parameter af te drukken.
dx -r2 @$cursession.TTD.Calls("kernelbase!CreateFileW").Where(x => x.Parameters.lpFileName.ToDisplayString("su").Contains("OLE")).Select(x => new { TimeStart = x.TimeStart, lpFileName = x.Parameters.lpFileName })
Als er een TTD.Calls-object wordt gevonden dat de doelgegevens bevat, wordt deze uitvoer gegenereerd.
[0x0]
TimeStart : 6E37:590
lpFileName : 0x346a78be90 : "C:\WINDOWS\SYSTEM32\OLEACCRC.DLL" [Type: wchar_t *]
Het aantal aanroepen in een trace weergeven
Nadat u de dx-opdracht hebt gebruikt om objecten te verkennen waarmee u wilt werken, kunt u het gebruik ervan automatiseren met JavaScript. In dit eenvoudige voorbeeld wordt het TTD.Calls object gebruikt om aanroepen naar kernelbase!GetLastError te tellen.
function CountLastErrorCalls()
{
var LastErrorCalls = host.currentSession.TTD.Calls("kernelbase!GetLastError");
host.diagnostics.debugLog(">>> GetLastError calls in this TTD recording: " + LastErrorCalls.Count() +" \n");
}
Sla het script op in een TTDUtils.js-bestand en roep het aan met behulp van de dx-opdracht om het aantal keren dat kernelbase!GetLastError voorkomt in het traceringsbestand weer te geven.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.CountLastErrorCalls()
>>> GetLastError calls in this TTD recording: 18
De frames in een stack weergeven
Als u de frames in een stack wilt weergeven, wordt een matrix gebruikt.
function DisplayStack()
{
// Create an array of stack frames in the current thread
const Frames = Array.from(host.currentThread.Stack.Frames);
host.diagnostics.debugLog(">>> Printing stack \n");
// Print out all of the frame entries in the array
for(const [Idx, Frame] of Frames.entries())
{
host.diagnostics.debugLog(">>> Stack Entry -> " + Idx + ": "+ Frame + " \n");
}
}
In deze voorbeeldtracering wordt de ene stack-vermelding weergegeven.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.DisplayStack()
>>> Printing stack
>>> Stack Entry -> 0: ntdll!LdrInitializeThunk + 0x21
Een gebeurtenis zoeken en de stack weergeven
In deze code bevinden alle uitzonderingen zich en wordt een lus gebruikt om naar elke gebeurtenis te gaan. Vervolgens wordt de currentThread.ID van de TTD-threadobjecten gebruikt om de thread-id en currentThread.Stack weer te geven om alle frames in de stack weer te geven.
function HardwareExceptionDisplayStack()
{
var exceptionEvents = host.currentProcess.TTD.Events.Where(t => t.Type == "Exception");
for (var curEvent of exceptionEvents)
{
// Move to the current event position
curEvent.Position.SeekTo();
host.diagnostics.debugLog(">>> The Thread ID (TID) is : " + host.currentThread.Id + "\n");
// Create an array of stack frames in the current thread
const Frames = Array.from(host.currentThread.Stack.Frames);
host.diagnostics.debugLog(">>> Printing stack \n");
// Print out all of the frame entries in the array
for(const [Idx, Frame] of Frames.entries()) {
host.diagnostics.debugLog(">>> Stack Entry -> " + Idx + ": "+ Frame + " \n");
}
host.diagnostics.debugLog("\n");
}
}
De uitvoer toont de locatie van de uitzonderingsgebeurtenis, de TID en de stackframes.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.HardwareExceptionDisplayStack()
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 91:0
>>> The Thread ID (TID) is : 5260
>>> Printing stack
>>> Stack Entry -> 0: 0x540020
>>> Stack Entry -> 1: 0x4d0049
>>> Stack Entry -> 2: DisplayGreeting!__CheckForDebuggerJustMyCode + 0x16d
>>> Stack Entry -> 3: DisplayGreeting!mainCRTStartup + 0x8
>>> Stack Entry -> 4: KERNEL32!BaseThreadInitThunk + 0x19
>>> Stack Entry -> 5: ntdll!__RtlUserThreadStart + 0x2f
>>> Stack Entry -> 6: ntdll!_RtlUserThreadStart + 0x1b
Een gebeurtenis zoeken en twee opdrachten verzenden
Het opvragen van TTD-objecten en het verzenden van opdrachten kan indien nodig worden gecombineerd. In dit voorbeeld wordt elke gebeurtenis in de TTD-trace van het type ThreadCreated gevonden, daarbij verplaatst naar die positie, en worden de ~Threadstatus en de !runaway-opdrachten verzonden om de threadstatus weer te geven.
function ThreadCreateThreadStatus()
{
var threadEvents = host.currentProcess.TTD.Events.Where(t => t.Type == "ThreadCreated");
for (var curEvent of threadEvents)
{
// Move to the current event position
curEvent.Position.SeekTo();
// Display Information about threads
host.namespace.Debugger.Utility.Control.ExecuteCommand("~", false);
host.namespace.Debugger.Utility.Control.ExecuteCommand("!runaway 7", false);
}
}
Als u de code uitvoert, wordt de threadstatus weergegeven op het moment dat de uitzondering heeft plaatsgevonden.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ThreadCreateThreadStatus()
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
. 0 Id: 948.148c Suspend: 4096 Teb: 00a33000 Unfrozen
User Mode Time
Thread Time
0:148c 0 days 0:00:00.000
Kernel Mode Time
Thread Time
0:148c 0 days 0:00:00.000
Elapsed Time
Thread Time
0:148c 3474 days 2:27:43.000
Het aan elkaar koppelen van hulpfuncties
In dit laatste voorbeeld kunnen we de hulpprogrammafuncties aanroepen die we eerder hebben gemaakt. Eerst indexeren we de trace met behulp van IndexTraceTry en roepen we threadCreateThreadStatus aan. Vervolgens gebruiken we ResetTrace om naar het begin van de trace te gaan en tot slot HardwareExceptionDisplayStack aan te roepen.
function ProcessTTDFiles()
{
try
{
IndexTraceTry()
ThreadCreateThreadStatus()
ResetTrace()
HardwareExceptionDisplayStack()
}
catch(err)
{
host.diagnostics.debugLog("\n >>> Processing of TTD file failed \n");
}
}
Als u dit script uitvoert op een traceringsbestand dat een hardware-uitzondering bevat, wordt deze uitvoer gegenereerd.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.ProcessTTDFiles()
>>> Index Return Value: Loaded
>>> Trace was successfully indexed in 0 ms
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
. 0 Id: 948.148c Suspend: 4096 Teb: 00a33000 Unfrozen
User Mode Time
Thread Time
0:148c 0 days 0:00:00.000
Kernel Mode Time
Thread Time
0:148c 0 days 0:00:00.000
Elapsed Time
Thread Time
0:148c 3474 days 2:27:43.000
>>> Printing stack
>>> Stack Entry -> 0: ntdll!LdrInitializeThunk
>>> Current position in trace file: F:0
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: F:0
>>> New position in trace file: F:0
(948.148c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 91:0
>>> The Thread ID (TID) is : 5260
>>> Printing stack
>>> Stack Entry -> 0: 0x540020
>>> Stack Entry -> 1: 0x4d0049
>>> Stack Entry -> 2: DisplayGreeting!__CheckForDebuggerJustMyCode + 0x16d
>>> Stack Entry -> 3: DisplayGreeting!mainCRTStartup + 0x8
>>> Stack Entry -> 4: KERNEL32!BaseThreadInitThunk + 0x19
>>> Stack Entry -> 5: ntdll!__RtlUserThreadStart + 0x2f
>>> Stack Entry -> 6: ntdll!_RtlUserThreadStart + 0x1b
Zie ook
Time Travel Debugging - Overzicht
Inleiding tot Time Travel Debugging-objecten