Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Interna felsökningsobjekt representerar olika konstruktioner och beteenden i felsökningsmiljön. Objekten kan skickas till (eller hämtas i) JavaScript-tillägg för att ändra tillståndet för felsökningsprogrammet.
Exempel på felsökningsobjekt är följande.
- Sittning
- Trådar/tråd
- Processer/process
- Stackramar/Stackram
- Lokala variabler
- Moduler/modul
- Nyttighet
- Stat/län
- Inställningar
Till exempel kan objektet host.namespace.Debugger.Utility.Control.ExecuteCommand användas för att skicka u-kommandot till felsökningsprogrammet med följande två rader JavaScript-kod.
var ctl = host.namespace.Debugger.Utility.Control;
var outputLines = ctl.ExecuteCommand("u");
Det här avsnittet beskriver hur du arbetar med vanliga objekt och innehåller referensinformation om deras attribut och beteenden.
Allmän information om hur du arbetar med JavaScript finns i Skript för JavaScript-felsökningsprogram. JavaScript-exempel som använder felsökningsobjekten finns i Exempelskript för JavaScript-felsökningsprogram. Information om hur du arbetar med inställningsobjekten finns i .settings (Set Debug Settings).
Om du vill utforska de objekt som är tillgängliga i en felsökningssession använder du kommandot dx (Display NatVis Expression). Du kan till exempel visa några av felsökningsobjekten på den översta nivån med det här dx-kommandot.
0: kd> dx -r2 Debugger
Debugger
Sessions : [object Object]
[0x0] : Remote KD: KdSrv:Server=@{<Local>},Trans=@{NET:Port=50000,Key=1.2.3.4,Target}
Settings
Debug
Display
EngineInitialization
Extensions
Input
Sources
Symbols
AutoSaveSettings : false
State
DebuggerVariables
PseudoRegisters
Scripts
UserVariables
Utility
Collections
Control
Objects
Alla objekt som anges ovan är klickbara DML och kan rekurseras längre ned för att visa objektstrukturen för felsökningsprogrammet.
Utöka felsökningsprogrammet via datamodellen
Datamodellen för felsökning gör det möjligt att skapa ett gränssnitt för information om program och drivrutiner i Windows som har följande attribut.
- Kan identifieras och organiseras – ett logiskt strukturerat namnutrymme kan efterfrågas med hjälp av dx-kommandot.
- Kan frågas med LINQ – Detta möjliggör extrahering och sortering av data med hjälp av ett standardfrågespråk.
- Kan utökas logiskt och konsekvent – Utökningsbar med hjälp av tekniker som beskrivs i det här avsnittet med skriptprovider för felsökningsprogram som Natvis och JavaScript.
Utöka ett felsökningsobjekt i JavaScript
Förutom att kunna skapa en visualiserare i JavaScript kan skripttillägg också ändra huvudbegreppen i felsökningsprogrammet – sessioner, processer, trådar, staplar, stackramar, lokala variabler – och till och med publicera sig själva som tilläggspunkter som andra tillägg kan använda.
I det här avsnittet beskrivs hur du utökar ett kärnkoncept i felsökningsprogrammet. Tillägg som har skapats för att delas bör följa riktlinjerna som presenteras i interna felsökningsobjekt i JavaScript-tillägg – Design- och testningsöverväganden.
Registrering av ett tillägg
Ett skript kan registrera det faktum att det tillhandahåller ett tillägg via en post i matrisen som returneras från metoden initializeScript.
function initializeScript()
{
return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process")];
}
Förekomsten av ett host.namedModelParent-objekt i den returnerade matrisen anger för felsökaren att ett visst prototypobjekt eller en ES6-klass (comProcessExtension i det här fallet) kommer att vara en överordnad datamodell till modellen som är registrerad under namnet Debugger.Models.Process.
Tilläggspunkter för felsökningsobjekt
Följande tilläggspunkter för felsökningsprogrammet är integrerade i felsökningsprogrammet och är tillgängliga för användning av skriptproviders som JavaScript.
Debugger.Models.Sessions: Listan över sessioner (mål) som felsökningsprogrammet är kopplat till
Debugger.Models.Session: En enskild session (mål) som felsökningsprogrammet är kopplat till (live-användarläge, KD osv.)
Debugger.Models.Processes: Listan över processer i en session
Debugger.Models.Threads: Listan över trådar i en process
Debugger.Models.Thread: En enskild tråd i en process (oavsett om användarläge eller kärnläge)
Debugger.Models.Stack: Trådens stack
Debugger.Models.StackFrames: Samlingen med bildrutor som utgör en stack
Debugger.Models.StackFrame: En enskild stack frame i en stack
Debugger.Models.LocalVariables: De lokala variablerna i en stackram
Debugger.Models.Parameters: Parametrarna för ett anrop inom en stackram
Debugger.Models.Module: En enskild modul inom adressutrymmet för en process
Ytterligare datamodellobjekt
Dessutom finns det några ytterligare datamodellobjekt som definieras av kärndatamodellen.
DataModel.Models.Intrinsic: Ett intrinsiskt värde (ordinaltal, flyttal osv.)
DataModel.Models.String: En sträng
DataModel.Models.Array: En intern matris
DataModel.Models.Guid: Ett GUID
DataModel.Models.Error: Ett felobjekt
DataModel.Models.Concepts.Iterable: Tillämpas på alla objekt som kan itereras
DataModel.Models.Concepts.StringDisplayable: Tillämpas på varje objekt som har en visningssträngkonvertering
Exempel på översikt över COM-felsökningsobjekttillägg
Låt oss ta ett exempel. Anta att du vill skapa ett felsökningstillägg för att visa information som är specifik för COM, till exempel den globala gränssnittstabellen (GIT).
Tidigare kan det finnas ett befintligt tillägg för felsökningsprogram med ett antal kommandon som ger ett sätt att komma åt saker om COM. Ett kommando kan visa processcentrerad information (till exempel den globala gränssnittstabellen). Ett annat kommando kan ge trådcentrerad information, till exempel vilken komponentkod som exekveras i. Du kan behöva känna till och läsa in ett andra debugger-tillägg för att utforska ytterligare aspekter av COM.
I stället för att ha en uppsättning svåra att identifiera kommandon kan ett JavaScript-tillägg ändra felsökningsprogrammets koncept för vad en process och en tråd är, för att lägga till den här informationen på ett sätt som är naturligt, utforskande och komposterbart med andra tillägg för felsökningsprogram.
Objekttillägg för felsökning i användar- eller kärnläge
Felsökningsprogrammet och felsökningsobjekten har olika beteende i användar- och kernelläge. När du skapar dina felsökningsmodellobjekt måste du bestämma vilka miljöer du ska arbeta i. Eftersom vi kommer att arbeta med COM i användarläge skapar och testar vi det här com-tillägget i användarläge. I andra situationer kan du kanske skapa ett JavaScript-felsökningsprogram som fungerar i både användar- och kernellägesfelsökning.
Skapa ett undernamnområde
När vi går tillbaka till vårt exempel kan vi definiera en prototyp eller ES6-klass, comProcessExtension som innehåller den uppsättning saker som vi vill lägga till i ett processobjekt.
Viktig Avsikten med undernamnområdet är att skapa ett logiskt strukturerat och naturligt utforskande paradigm. Undvik till exempel att dumpa orelaterade objekt i samma undernamnområde. Granska noggrant informationen som beskrivs i interna felsökningsobjekt i JavaScript-tillägg – Design- och testningsöverväganden innan du skapar ett undernamnområde.
I det här kodfragmentet skapar vi lägga till ett undernamnområde med namnet "COM" på det befintliga processfelsökarobjektet.
var comProcessExtension =
{
//
// Add a sub-namespace called 'COM' on process.
//
get COM()
{
//
// What is 'this' below...? It's the debugger's process object. Yes -- this means that there is a cross-language
// object hierarchy here. A C++ object implemented in the debugger has a parent model (prototype) which is
// implemented in JavaScript.
//
return new comNamespace(this);
}
}
Implementering av namnområde
Skapa sedan objektet som implementerar undernamnområdet COM i en process.
Viktig Det kan finnas flera processer (oavsett om de är kopplade till sådana i användarläge eller under KD). Det här tillägget kan inte förutsätta att det aktuella tillståndet för felsökningsprogrammet är det som användaren avsåg. Någon kan fånga <vissaProcess>.COM i en variabel och ändra den, vilket kan leda till att presentera information från fel processkontext. Lösningen är att lägga till kod i tillägget så att varje instansiering håller reda på vilken process den är kopplad till. För det här kodexemplet skickas informationen via "this"-pekaren för egenskapen.
this.__process = process;
class comNamespace
{
constructor(process)
{
//
// This is an entirely JavaScript object. Each instantiation of a comNamespace will keep track
// of what process it is attached to (passed via the ''this'' pointer of the property getter
// we authored above.
//
this.__process = process;
}
get GlobalObjects()
{
return new globalObjects(this.__process);
}
}
Implementeringslogik för den globala COM-gränssnittstabellen
För att avgränsa implementeringslogik för den globala COM-gränssnittstabellen tydligare definierar vi en ES6-klass, gipTable som abstraherar bort COM GIP-tabellen och en annan, globalObjects, vilket är vad som returneras från Den GlobalObjects() getter som definieras i kodfragmentet För namnområdesimplementering som visas ovan. All den här informationen kan döljas i stängningen av InitializeScript för att undvika att publicera någon av dessa interna uppgifter i namnområdet för felsökningsprogrammet.
// gipTable:
//
// Internal class which abstracts away the GIP Table. It iterates objects of the form
// {entry : GIPEntry, cookie : GIT cookie}
//
class gipTable
{
constructor(gipProcess)
{
//
// Windows 8 through certain builds of Windows 10, it's in CGIPTable::_palloc. In certain builds
// of Windows 10 and later, this has been moved to GIPEntry::_palloc. We need to check which.
//
var gipAllocator = undefined;
try
{
gipAllocator = host.getModuleSymbol("combase.dll", "CGIPTable::_palloc", "CPageAllocator", gipProcess)._pgalloc;
}
catch(err)
{
}
if (gipAllocator == undefined)
{
gipAllocator = host.getModuleSymbol("combase.dll", "GIPEntry::_palloc", "CPageAllocator", gipProcess)._pgalloc;
}
this.__data = {
process : gipProcess,
allocator : gipAllocator,
pageList : gipAllocator._pPageListStart,
pageCount : gipAllocator._cPages,
entriesPerPage : gipAllocator._cEntriesPerPage,
bytesPerEntry : gipAllocator._cbPerEntry,
PAGESHIFT : 16,
PAGEMASK : 0x0000FFFF,
SEQNOMASK : 0xFF00
};
}
*[Symbol.iterator]()
{
for (var pageNum = 0; pageNum < this.__data.pageCount; ++pageNum)
{
var page = this.__data.pageList[pageNum];
for (var entryNum = 0; entryNum < this.__data.entriesPerPage; ++entryNum)
{
var entryAddress = page.address.add(this.__data.bytesPerEntry * entryNum);
var gipEntry = host.createPointerObject(entryAddress, "combase.dll", "GIPEntry *", this.__data.process);
if (gipEntry.cUsage != -1 && gipEntry.dwType != 0)
{
yield {entry : gipEntry, cookie : (gipEntry.dwSeqNo | (pageNum << this.__data.PAGESHIFT) | entryNum)};
}
}
}
}
entryFromCookie(cookie)
{
var sequenceNo = (cookie & this.__data.SEQNOMASK);
cookie = cookie & ~sequenceNo;
var pageNum = (cookie >> this.__data.PAGESHIFT);
if (pageNum < this.__data.pageCount)
{
var page = this.__data.pageList[pageNum];
var entryNum = (cookie & this.__data.PAGEMASK);
if (entryNum < this.__data.entriesPerPage)
{
var entryAddress = page.address.add(this.__data.bytesPerEntry * entryNum);
var gipEntry = host.createPointerObject(entryAddress, "combase.dll", "GIPEntry *", this.__data.process);
if (gipEntry.cUsage != -1 && gipEntry.dwType != 0 && gipEntry.dwSeqNo == sequenceNo)
{
return {entry : gipEntry, cookie : (gipEntry.dwSeqNo | (pageNum << this.__data.PAGESHIFT) | entryNum)};
}
}
}
//
// If this exception flows back to C/C++, it will be a failed HRESULT (according to the type of error -- here E_BOUNDS)
// with the message being encapsulated by an error object.
//
throw new RangeError("Unable to find specified value");
}
}
// globalObjects:
//
// The class which presents how we want the GIP table to look to the data model. It iterates the actual objects
// in the GIP table indexed by their cookie.
//
class globalObjects
{
constructor(process)
{
this.__gipTable = new gipTable(process);
}
*[Symbol.iterator]()
{
for (var gipCombo of this.__gipTable)
{
yield new host.indexedValue(gipCombo.entry.pUnk, [gipCombo.cookie]);
}
}
getDimensionality()
{
return 1;
}
getValueAt(cookie)
{
return this.__gipTable.entryFromCookie(cookie).entry.pUnk;
}
}
Slutligen använder du host.namedModelRegistration för att registrera de nya COM-funktionerna.
function initializeScript()
{
return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process"),
new host.namedModelRegistration(comNamespace, "Debugger.Models.ComProcess")];
}
Spara koden till GipTableAbstractor.js med hjälp av ett program, till exempel Anteckningar.
Här är processinformationen som är tillgänglig i användarläge innan du läser in det här tillägget.
0:000:x86> dx @$curprocess
@$curprocess : DataBinding.exe
Name : DataBinding.exe
Id : 0x1b9c
Threads
Modules
Läs in JavaScript-tillägget.
0:000:x86> .scriptload C:\JSExtensions\GipTableAbstractor.js
JavaScript script successfully loaded from 'C:\JSExtensions\GipTableAbstractor.js'
Använd sedan dx-kommandot för att visa information om processen med hjälp av den fördefinierade @$curprocess.
0:000:x86> dx @$curprocess
@$curprocess : DataBinding.exe
Name : DataBinding.exe
Id : 0x1b9c
Threads
Modules
COM : [object Object]
0:000:x86> dx @$curprocess.COM
@$curprocess.COM : [object Object]
GlobalObjects : [object Object]
0:000:x86> dx @$curprocess.COM.GlobalObjects
@$curprocess.COM.GlobalObjects : [object Object]
[0x100] : 0x12f4fb0 [Type: IUnknown *]
[0x201] : 0x37cfc50 [Type: IUnknown *]
[0x302] : 0x37ea910 [Type: IUnknown *]
[0x403] : 0x37fcfe0 [Type: IUnknown *]
[0x504] : 0x12fe1d0 [Type: IUnknown *]
[0x605] : 0x59f04e8 [Type: IUnknown *]
[0x706] : 0x59f0eb8 [Type: IUnknown *]
[0x807] : 0x59f5550 [Type: IUnknown *]
[0x908] : 0x12fe340 [Type: IUnknown *]
[0xa09] : 0x5afcb58 [Type: IUnknown *]
Den här tabellen är också programmatiskt tillgänglig via GIT-cookie.
0:000:x86> dx @$curprocess.COM.GlobalObjects[0xa09]
@$curprocess.COM.GlobalObjects[0xa09] : 0x5afcb58 [Type: IUnknown *]
[+0x00c] __abi_reference_count [Type: __abi_FTMWeakRefData]
[+0x014] __capture [Type: Platform::Details::__abi_CapturePtr]
Utöka begrepp för felsökningsobjekt med LINQ
Förutom att kunna utöka objekt som process och tråd kan JavaScript även utöka begrepp som är associerade med datamodellen. Det går till exempel att lägga till en ny LINQ-metod till varje iterabel. Överväg ett exempeltillägg, "DuplicateDataModel" som duplicerar varje post i en iterabel N gånger. Följande kod visar hur detta kan implementeras.
function initializeScript()
{
var newLinqMethod =
{
Duplicate : function *(n)
{
for (var val of this)
{
for (var i = 0; i < n; ++i)
{
yield val;
}
};
}
};
return [new host.namedModelParent(newLinqMethod, "DataModel.Models.Concepts.Iterable")];
}
Spara koden till DuplicateDataModel.js, använd ett program som Anteckningar.
Ladda skriptleverantören för JavaScript om det behövs och ladda sedan in tillägget DuplicateDataModel.js.
0:000:x86> !load jsprovider.dll
0:000:x86> .scriptload C:\JSExtensions\DuplicateDataModel.js
JavaScript script successfully loaded from 'C:\JSExtensions\DuplicateDataModel.js'
Använd dx-kommandot för att testa den nya duplicerade funktionen.
0: kd> dx -r1 Debugger.Sessions.First().Processes.First().Threads.Duplicate(2),d
Debugger.Sessions.First().Processes.First().Threads.Duplicate(2),d : [object Generator]
[0] : nt!DbgBreakPointWithStatus (fffff800`9696ca60)
[1] : nt!DbgBreakPointWithStatus (fffff800`9696ca60)
[2] : intelppm!MWaitIdle+0x18 (fffff805`0e351348)
[3] : intelppm!MWaitIdle+0x18 (fffff805`0e351348)
…
Se även
Interna felsökningsobjekt i JavaScript-tillägg – Information om felsökningsobjekt
Interna felsökningsobjekt i JavaScript-tillägg – Design- och testningsöverväganden