Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A JavaScript automation használatával többféleképpen is használhat TTD-nyomkövetéseket, például parancsautomatizálást vagy lekérdezéseket a nyomkövetési fájl eseményadatainak megkereséséhez.
A JavaScript használatával kapcsolatos általános információkért lásd a JavaScript Hibakereső szkriptkészítést. Vannak JavaScript Hibakereső példaszkriptek is.
JavaScript TTD parancsautomatizálás
A JavaScript TTD-automatizáláshoz való használatának egyik módja, ha parancsokat küld az időutazási nyomkövetési fájlok használatának automatizálásához.
Mozgás egy nyomkövetési fájlban
Ez a JavaScript bemutatja, hogyan válthat az időutazási nyomkövetés elejére a !tt paranccsal.
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");
Ezt egy ResetTrace függvénybe állíthatjuk be, és MyTraceUtils.jsformátumban menthetjük a WinDbg JavaScript felhasználói felületével.
// 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");
}
Miután betöltött egy TTD-fájlt a WinDbg-be, hívja meg a ResetTraceCmd() függvényt a hibakereső parancsablak dx parancsával.
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()
A parancsok küldésének korlátozásai
A legegyszerűbb helyzeteken kívül azonban a parancsok küldésének megközelítése hátrányokat jelent. A szövegkimenet használatára támaszkodik. A kimenet elemzése pedig törékeny és nehezen karbantartható kódhoz vezet. Jobb módszer a TTD-objektumok közvetlen használata.
Az alábbi példa bemutatja, hogyan használhatja közvetlenül az objektumokat ugyanazon feladat közvetlen végrehajtására az objektumok használatával.
// 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");
}
A kód futtatása azt mutatja, hogy át tudunk lépni a nyomkövetési fájl elejére.
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
Ebben a példában a ResetTraceEnd függvény a nyomkövetés végére állítja a pozíciót, az aktuális és az új pozíció pedig a currentThread.TTD Position objektummal jelenik meg.
// 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");
}
A kód futtatása az aktuális és az új pozíciót jeleníti meg.
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
Ebben a kibontott mintában a kezdő és a záró pozíció értékeit hasonlítjuk össze, hogy kiderüljön, változott-e a nyomkövetési pozíció.
// 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");
}
}
A példafuttatás során egy olyan üzenet jelenik meg, amely szerint a nyomkövetési fájl elején mindannyian készen voltunk.
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
A szkript teszteléséhez a !tt paranccsal navigáljon félúton a nyomkövetési fájlban.
0:000> !tt 50
Setting position to 50% into the trace
Setting position: 71:0
A szkript futtatása ekkor megjeleníti a megfelelő üzenetet, amely azt jelzi, hogy a pozíció a TTD-nyomkövetés kezdetére lett beállítva.
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
Időutazási nyomkövetési fájl indexelése
Ha csak egy nyomkövetési fájlt másol át egy másik számítógépre, újra kell indexelni. További információ: Time Travel Hibakeresés – Nyomkövetési fájlok használata.
Ez a kód egy példa IndexTrace függvényt mutat be, amely megjeleníti, hogy mennyi ideig tart egy nyomkövetési fájl újraindexelése.
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");
}
Íme egy kis nyomkövetési fájl kimenete.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTrace()
>>> Trace was indexed in 2 ms
Try catch utasítás hozzáadása
Ha ellenőrizni szeretné, hogy az indexelés futtatásakor hibák jelentkeztek-e, helyezze az indexelési kódot egy try-catch blokkba.
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");
}
}
Ha az indexelés sikeres, az alábbi parancsprogram kimenete jelenik meg.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTraceTry()
>>> Index Return Value: Loaded
>>> Trace was successfully indexed in 1 ms
Ha a nyomkövetés nem indexelhető, például ha a nyomkövetés nincs betöltve a hibakeresőbe, futtatják az elkapási ciklus kódját.
0:007> dx Debugger.State.Scripts.MyTraceUtils.Contents.IndexTraceTry()
>>> Index Failed!
>>> Index Return Value: undefined
>>> Returned error: TypeError
JavaScript TTD-objektumok lekérdezései
A JavaScript és a TTD fejlettebb használata az időutazási objektumok lekérdezése a nyomkövetésben történt hívások vagy események megkereséséhez. A TTD-objektumokkal kapcsolatos további információkért lásd:
Bevezetés a Time Travel hibakeresési objektumaiba
Natív hibakereső objektumok JavaScript-bővítményekben – Hibakereső objektum részletei
A dx parancs megjeleníti a hibakereső adatmodellből származó információkat, és támogatja a LINQ szintaxist használó lekérdezéseket. A Dx nagyon hasznos az objektumok valós idejű lekérdezéséhez. Ez lehetővé teszi a kívánt lekérdezés prototípusát, amelyet aztán a JavaScript használatával automatizálhat. A dx parancs lapkiegészítést biztosít, ami hasznos lehet az objektummodell feltárásakor. A LINQ-lekérdezések és hibakereső objektumok használatával kapcsolatos általános információkért tekintse meg a LINQ használata a hibakereső objektumokkal című témakört.
Ez a dx parancs megszámolja egy adott API összes hívását ebben a példában : GetLastError.
0:000> dx @$cursession.TTD.Calls("kernelbase!GetLastError").Count()
@$cursession.TTD.Calls("kernelbase! GetLastError").Count() : 0x12
Ez a parancs a teljes időutazási nyomkövetésben megtekinti, hogy mikor lett meghívva a GetLastError.
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]
Szövegösszehasonlítások a TTD.Calls objektumhoz a hívások megtalálásához
Ez a példaparancs bemutatja, hogyan használhat sztring-összehasonlításokat adott hívások megkereséséhez. Ebben a példában a lekérdezés az "OLE" sztringet keresi a CreateFileW függvény lpFileName paraméterében.
dx -r2 @$cursession.TTD.Calls("kernelbase!CreateFileW").Where(x => x.Parameters.lpFileName.ToDisplayString("su").Contains("OLE"))
Adjon hozzá egy .Select utasítást a Timestart és az lpFileName paraméter értékének nyomtatásához.
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 })
Ez generálja ezt a kimenetet, ha található egy TTD.Calls objektum, amely tartalmazza a céladatokat.
[0x0]
TimeStart : 6E37:590
lpFileName : 0x346a78be90 : "C:\WINDOWS\SYSTEM32\OLEACCRC.DLL" [Type: wchar_t *]
A hívások számának megjelenítése nyomkövetésben
Miután a dx paranccsal feltárta a használni kívánt objektumokat, automatizálhatja a JavaScripttel való használatukat. Ebben az egyszerű példában a TTD.Calls objektumot a kernelbase!GetLastError hívások számolására használjuk.
function CountLastErrorCalls()
{
var LastErrorCalls = host.currentSession.TTD.Calls("kernelbase!GetLastError");
host.diagnostics.debugLog(">>> GetLastError calls in this TTD recording: " + LastErrorCalls.Count() +" \n");
}
Mentse a szkriptet egy TTDUtils.js fájlba, és hívja meg a dx paranccsal, hogy megjelenítse a kernelbase!GetLastError előfordulásainak számát a nyomkövetési fájlban.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.CountLastErrorCalls()
>>> GetLastError calls in this TTD recording: 18
A keretek megjelenítése halmazban
A keretek veremben való megjelenítéséhez tömböt használunk.
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");
}
}
Ebben a mintakövetésben megjelenik az egyetlen verembejegyzés.
0:000> dx Debugger.State.Scripts.MyTraceUtils.Contents.DisplayStack()
>>> Printing stack
>>> Stack Entry -> 0: ntdll!LdrInitializeThunk + 0x21
Esemény megkeresése és a verem megjelenítése
Ebben a kódban az összes kivételesemény található, és a rendszer egy hurkot használ az egyes eseményekre való áttéréshez. A TTD thread objektumok currentThread.ID a szálazonosító megjelenítésére szolgál, míg a currentThread.Stack a verem összes képkockájának megjelenítésére szolgál.
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");
}
}
A kimenet a kivételi esemény helyét, a TID-t és a veremkereteket jeleníti meg.
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
Esemény keresése és két parancs küldése
A TTD-objektumok lekérdezése és a parancsok küldése szükség szerint kombinálható. Ez a példa megkeresi az egyes eseményeket a ThreadCreated típusú TTD-nyomkövetésben, erre a pozícióra lép, és elküldi a ~ Szál állapota és a !runaway parancsokat a szál állapotának megjelenítéséhez.
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);
}
}
A kód futtatása megjeleníti a szál állapotát abban a pillanatban, amikor a kivétel történt.
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
A segédfüggvények összefűzése
Ebben az utolsó mintában meghívhatjuk a korábban létrehozott segédprogramfüggvényeket. Először indexeljük a nyomkövetést az IndexTraceTry használatával, majd meghívjuk a ThreadCreateThreadStatus parancsot. Ezután a ResetTrace használatával lépünk a nyomkövetés elejére, és végül meghívjuk a HardwareExceptionDisplayStack parancsot.
function ProcessTTDFiles()
{
try
{
IndexTraceTry()
ThreadCreateThreadStatus()
ResetTrace()
HardwareExceptionDisplayStack()
}
catch(err)
{
host.diagnostics.debugLog("\n >>> Processing of TTD file failed \n");
}
}
Egy nyomkövetési fájlon futtatva, amely hardverkivételt tartalmaz, ez a script ezt a kimenetet hozza létre.
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
Lásd még:
Time Travel Hibakeresés – Áttekintés
Bevezetés a Time Travel hibakeresési objektumaiba
Natív hibakereső objektumok JavaScript-bővítményekben – Hibakereső objektum részletei