Megosztás a következőn keresztül:


Natív hibakereső objektumok JavaScript-bővítményekben

A natív hibakereső objektumok a hibakereső környezet különböző szerkezeteit és viselkedését jelölik. Az objektumok átadhatók (vagy beszerezhetők) JavaScript-bővítményekbe a hibakereső állapotának módosításához.

A hibakereső objektumok közé tartoznak például a következők.

  • Ülés
  • Szálak / szál
  • Folyamatok / folyamat
  • Stack Frames /Stack Frame
  • Helyi változók
  • Modulok / modul
  • Hasznosság
  • Állam
  • Beállítások

Például a host.namespace.Debugger.Utility.Control.ExecuteCommand objektum segítségével elküldheti az u parancsot a hibakeresőnek két SorNyi JavaScript-kóddal.

var ctl = host.namespace.Debugger.Utility.Control;   
var outputLines = ctl.ExecuteCommand("u");

Ez a témakör bemutatja, hogyan használható a gyakori objektumok, és referenciainformációkat nyújt az attribútumaikról és viselkedésükről.

A JavaScript használatával kapcsolatos általános információkért tekintse meg a JavaScript Hibakereső szkriptkészítés című témakört. A hibakereső objektumokat használó JavaScript-példákért lásd a JavaScript Hibakereső példaszkripteket. A beállításobjektumok használatával kapcsolatos további információkért lásd a .settings (Hibakeresési beállítások beállítása) című témakört.

A hibakereső munkamenetben elérhető objektumok felderítéséhez használja a dx (NatVis-kifejezés megjelenítése) parancsot. Megjeleníthet például néhány legfelső szintű hibakereső objektumot ezzel a dx paranccsal.

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   

A fent felsorolt elemek mindegyike kattintható DML, és tovább lehet navigálni, hogy megnézhessük a hibakereső objektumok szerkezetét.

A hibakereső kiterjesztése az adatmodellen keresztül

A hibakereső adatmodell lehetővé teszi egy felület létrehozását a Windowsban található alkalmazásokkal és illesztőprogramokkal kapcsolatos információkhoz, amelyek az alábbi attribútumokkal rendelkeznek.

  • Felderíthető és rendszerezhető. A logikailag strukturált névtér lekérdezhető a dx paranccsal.
  • A LINQ használatával lekérdezhető– Ez lehetővé teszi az adatok kinyerését és rendezését egy szabványos lekérdezési nyelv használatával.
  • Logikailag és konzisztensen bővíthető – Bővíthető a jelen témakörben ismertetett technikákkal olyan hibakereső szkriptszolgáltatókkal, mint a Natvis és a JavaScript.

Hibakereső objektum kiterjesztése JavaScriptben

Amellett, hogy képes vizualizációt létrehozni a JavaScriptben, a szkriptbővítmények módosíthatják a hibakereső alapvető fogalmait is – munkameneteket, folyamatokat, szálakat, vermeket, veremkereteket, helyi változókat –, és akár olyan bővítménypontokként is közzétehetik magukat, amelyeket más bővítmények felhasználhatnak.

Ez a szakasz azt ismerteti, hogyan terjeszthet ki alapvető fogalmat a hibakeresőn belül. A megosztani kívánt bővítményeknek meg kell felelniük a JavaScript-bővítmények natív hibakereső objektumaiban – tervezési és tesztelési szempontokban ismertetett irányelveknek.

Bővítmény regisztrálása

A szkript regisztrálhatja azt a tényt, hogy egy bővítményt nyújt az initializeScript metódus által visszaadott tömb egyik bejegyzése útján.

function initializeScript()
{
    return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process")];
}

A visszaadott tömbben egy host.namedModelParent objektum jelenléte azt jelzi a hibakeresőnek, hogy egy adott prototípusobjektum vagy ES6-osztály (ebben az esetben a comProcessExtension) szülőadatmodell lesz a Debugger.Models.Process néven regisztrált modellhez.

Hibakereső objektumbővítési pontok

Az alábbi hibakereső bővítménypontok a hibakereső szerves részét képezik, és olyan szkriptszolgáltatók számára érhetők el, mint a JavaScript.

Debugger.Models.Sessions: A hibakereső által csatolt munkamenetek (célok) listája

Debugger.Models.Session: Egy egyéni munkamenet (cél), amelyhez a hibakereső csatlakoztatva van (élő felhasználói mód, KD stb.)

Debugger.Models.Processes: A munkameneten belüli folyamatok listája

Debugger.Models.Threads: A folyamaton belüli szálak listája

Debugger.Models.Thread: Egy folyamat egyes szálai (függetlenül attól, hogy a felhasználó vagy a kernel mód)

Debugger.Models.Stack: A szál vereme

Debugger.Models.StackFrames: A vermet alkotó keretek gyűjteménye

Debugger.Models.StackFrame: Egy egyes veremkeret egy veremen belül

Debugger.Models.LocalVariables: A veremkereten belüli helyi változók

Debugger.Models.Parameters: A hívás paraméterei egy veremkereten belül

Debugger.Models.Module: Egy egyéni modul egy folyamat címterén belül

További adatmodell-objektumok

Emellett vannak további adatmodell-objektumok is, amelyeket az alapvető adatmodell határoz meg.

DataModel.Models.Intrinsic: Belső érték (sorszámok, lebegőpontos számok stb.)

DataModel.Models.String: Karakterlánc

DataModel.Models.Array: Natív tömb

DataModel.Models.Guid: Egy GUID

DataModel.Models.Error: Hibaobjektum

DataModel.Models.Concepts.Iterable: Minden iterható objektumra alkalmazva

DataModel.Models.Concepts.StringDisplayable: Minden olyan objektumra alkalmazva, amely rendelkezik szöveges megjelenítési átalakítással.

Példa COM hibakereső objektumbővítményre – áttekintés

Vegyünk egy példát. Tegyük fel, hogy létre szeretne hozni egy hibakeresőbővítményt, amely a COM-ra jellemző információkat jeleníti meg, például a globális felületi táblát (GIT).

A múltban előfordulhat, hogy egy meglévő hibakereső bővítmény számos parancsgal rendelkezik, amely lehetővé teszi a COM-val kapcsolatos dolgok elérését. Egy parancs megjelenítheti a folyamatközpontú információkat (például a globális interfésztáblát). Egy másik parancs szálcentrikus információkat adhat meg, például azt, hogy milyen lakáskód hajt végre benne. Előfordulhat, hogy a COM egyéb aspektusainak megismeréséhez tudnia kell és be kell töltenie egy második hibakeresőbővítményt.

Ahelyett, hogy nehezen felderíthető parancsokat használna, a JavaScript-bővítmények módosíthatják a hibakeresőnek a folyamat és a szál fogalmát, hogy ezeket az információkat természetes, felderíthető és más hibakereső bővítményekkel összefűzhető módon adja hozzá.

Felhasználó vagy kernel mód hibakereső objektumbővítménye

A hibakereső és a hibakereső objektum eltérő viselkedést alkalmaz felhasználói és kernel módban. A hibakereső modellobjektumok létrehozásakor el kell döntenie, hogy mely környezetekben fog dolgozni. Mivel a COM-val felhasználói módban fogunk dolgozni, felhasználói módban fogjuk létrehozni és tesztelni ezt a com-bővítményt. Más helyzetekben létrehozhat egy hibakereső JavaScriptet, amely a felhasználói és a kernel módú hibakeresésben is működni fog.

Alnévtér létrehozása

Visszatérve a példánkra, meghatározhatunk egy prototípust vagy ES6-osztályt, a comProcessExtensiont , amely tartalmazza a folyamatobjektumhoz hozzáadni kívánt dolgokat.

Fontos Az alnévtér célja egy logikailag strukturált és természetesen feltárható paradigma létrehozása. Kerülje például a nem kapcsolódó elemek ugyanabba az alnévtérbe csoportosítását. Alnévtér létrehozása előtt gondosan tekintse át a JavaScript-bővítmények natív hibakereső objektumaiban tárgyalt információkat – Tervezési és tesztelési szempontok .

Ebben a kódrészletben létrehozunk egy "COM" nevű alnévteret a meglévő folyamatkereső objektumhoz.

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);
    }
}

Névtér implementálása

Ezután hozza létre azt az objektumot, amely implementálja a COM alnévteret egy folyamaton.

Fontos Több folyamat is lehet (akár felhasználói módban, akár KD alatt csatolva van). Ez a bővítmény nem vehetjük biztosra, hogy a hibakereső jelenlegi állapota az, ami a felhasználó szándéka szerint van. Valaki rögzíthet <néhányProcess>.COM egy változóban, és módosíthatja azt, ami rossz folyamatkörnyezetből származó információk bemutatásához vezethet. A megoldás az, hogy kódot ad hozzá a bővítményhez, így minden példány nyomon követi, hogy milyen folyamathoz van csatolva. Ebben a kódmintában ezt az információt a tulajdonság "ez" mutatója adja át.

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);
    }
}

Implementálási logika a COM globális felületi táblához

Ha ezt jobban el szeretné különíteni a COM globális felület táblájának implementálási logikájától, meghatározunk egy ES6-osztályt, egy gipTable-t , amely elvonja a COM GIP-táblát és egy másik globalObjects-et, amely a fent látható Névtér-implementáció kódsznip-ben definiált GlobalObjects() getterből lesz visszaadva. Ezek a részletek az initializeScript lezárásánál rejthetők el, hogy ne kerüljenek közzétételre ezek a belső részletek a hibakereső névterében.

// 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;
    }
}

Végül használja a host.namedModelRegistration parancsot az új COM-funkciók regisztrálásához.

function initializeScript()
{
    return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process"),
            new host.namedModelRegistration(comNamespace, "Debugger.Models.ComProcess")];
}

Mentse a kódot a GipTableAbstractor.js-ba egy alkalmazás, például a jegyzettömb használatával.

A bővítmény betöltése előtt az alábbi folyamatinformációk érhetők el felhasználói módban.

0:000:x86> dx @$curprocess
@$curprocess                 : DataBinding.exe
    Name             : DataBinding.exe
    Id               : 0x1b9c
    Threads         
    Modules  

Töltse be a JavaScript-bővítményt.

0:000:x86> .scriptload C:\JSExtensions\GipTableAbstractor.js
JavaScript script successfully loaded from 'C:\JSExtensions\GipTableAbstractor.js'

Ezután a dx paranccsal megjelenítheti a folyamat adatait az előre definiált @$curprocess használatával.

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 *]

Ez a táblázat git cookie-k segítségével programozott módon is elérhető.

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]

Hibakereső objektumfogalmak kiterjesztése a LINQ-val

Amellett, hogy kiterjesztheti az olyan objektumokat, mint a folyamat vagy a szál, a JavaScript az adatmodellhez kapcsolódó fogalmakat is kiterjesztheti. Például minden iterálhatóhoz hozzáadhat egy új LINQ-metódust. Vegyük például a "DuplicateDataModel" bővítményt, amely ismétlődő N-alkalommal duplikálja az összes bejegyzést. Az alábbi kód bemutatja, hogyan implementálható ez a kód.

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")];
}

Mentse a kódot a DuplicateDataModel.js-ba egy alkalmazás, például a Jegyzettömb használatával.

Szükség esetén töltse be a JavaScript-szkriptszolgáltatót, majd töltse be a DuplicateDataModel.js bővítményt.

0:000:x86> !load jsprovider.dll
0:000:x86> .scriptload C:\JSExtensions\DuplicateDataModel.js
JavaScript script successfully loaded from 'C:\JSExtensions\DuplicateDataModel.js'

A dx paranccsal tesztelje az új Duplikált függvényt.

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) 
…

Lásd még

Natív hibakereső objektumok JavaScript-bővítményekben – Hibakereső objektum részletei

Natív hibakereső objektumok JavaScript-bővítményekben – Tervezési és tesztelési szempontok

JavaScript-hibakereső szkriptelése

JavaScript-hibakereső példaszkriptjei