Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Yerel hata ayıklayıcı nesneleri, hata ayıklayıcı ortamının çeşitli yapılarını ve davranışlarını temsil eder. Nesneler, hata ayıklayıcının durumunu değiştirmek için JavaScript uzantılarına geçirilebilir (veya içinde edinilebilir).
Örnek hata ayıklayıcı nesneleri aşağıdakileri içerir.
- Oturum
- İş Parçacıkları / İş Parçacığı
- İşlemler / İşlemler
- Yığın Çerçeveleri / Yığın Çerçevesi
- Yerel Değişkenler
- Modüller / Modül
- Fayda
- Devlet
- Ayarlar
Örneğin host.namespace.Debugger.Utility.Control.ExecuteCommand nesnesi, aşağıdaki iki JavaScript kodu satırıyla u komutunu hata ayıklayıcıya göndermek için kullanılabilir.
var ctl = host.namespace.Debugger.Utility.Control;
var outputLines = ctl.ExecuteCommand("u");
Bu konuda, ortak nesnelerle nasıl çalışıldığı açıklanır ve öznitelikleri ve davranışları hakkında başvuru bilgileri sağlanır.
JavaScript ile çalışma hakkında genel bilgi için bkz. JavaScript Hata Ayıklayıcısı Betiği Oluşturma. Hata ayıklayıcı nesnelerini kullanan JavaScript örnekleri için bkz. JavaScript Hata Ayıklayıcısı Örnek Betikleri. Ayarlar nesneleriyle çalışma hakkında bilgi için bkz. .settings (Hata Ayıklama Ayarlarını Ayarla).
Hata ayıklayıcı oturumunda kullanılabilen nesneleri keşfetmek için dx (NatVis İfadesini Görüntüle) komutunu kullanın. Örneğin, bu dx komutuyla en üst düzey hata ayıklayıcı nesnelerinden bazılarını görüntüleyebilirsiniz.
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
Yukarıda listelenen tüm öğeler tıklanabilir DML'dir ve hata ayıklayıcı nesne yapısını görüntülemek için daha aşağı doğru yinelenebilir.
Veri Modeli aracılığıyla Hata Ayıklayıcıyı Genişletme
Hata ayıklayıcısı veri modeli, Windows'ta aşağıdaki özniteliklere sahip uygulamalar ve sürücüler hakkında bilgi almak için bir arabirim oluşturulmasına olanak tanır.
- Bulunabilir ve düzenlidir; mantıksal olarak yapılandırılmış bir ad alanı dx komutu kullanılarak sorgulanabilir.
- LINQ kullanılarak sorgulanabilir- Bu, standart sorgu dili kullanılarak verilerin ayıklanıp sıralanmasına olanak tanır.
- Mantıksal ve tutarlı olarak genişletilebilir - Natvis ve JavaScript gibi hata ayıklayıcı betik sağlayıcılarıyla bu konuda açıklanan teknikler kullanılarak genişletilebilir.
JavaScript'te Hata Ayıklayıcı Nesnesini Genişletme
Betik uzantıları, JavaScript'te görselleştirici oluşturmanın yanı sıra oturumlar, işlemler, iş parçacıkları, yığınlar, yığın çerçeveleri, yerel değişkenler gibi hata ayıklayıcının temel kavramlarını değiştirebilir ve hatta kendilerini diğer uzantıların kullanabileceği uzantı noktaları olarak yayımlayabilir.
Bu bölümde, hata ayıklayıcısı içinde temel kavramın nasıl genişletıldığı açıklanmaktadır. Paylaşılacak şekilde oluşturulan uzantılar , JavaScript Uzantılarında Yerel Hata Ayıklayıcı Nesneleri - Tasarım ve Test Konuları'nda sunulan yönergelere uygun olmalıdır.
Uzantı Kaydetme
Betik, initializeScript yönteminden döndürülen dizideki bir girdi aracılığıyla bir uzantı sağladığı gerçeğini kaydedebilir.
function initializeScript()
{
return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process")];
}
Döndürülen dizide host.namedModelParent nesnesinin varlığı, hata ayıklayıcıya belirli bir prototip nesnesinin veya ES6 sınıfının (bu örnekte comProcessExtension) Debugger.Models.Process adı altında kayıtlı olan modele bir üst veri modeli olacağını gösterir.
Debugger Nesne Uzantısı Noktaları
Aşağıdaki hata ayıklayıcı uzantı noktaları hata ayıklayıcının ayrılmaz parçasıdır ve JavaScript gibi betik sağlayıcıları tarafından kullanılabilir.
Debugger.Models.Sessions: Hata ayıklayıcının eklendiği oturumların (hedefler) listesi
Debugger.Models.Session: Hata ayıklayıcının bağlı olduğu tek bir oturum (hedef) (canlı kullanıcı modu, KD vb.)
Debugger.Models.Processes: Oturum içindeki işlemlerin listesi
Debugger.Models.Threads: İşlem içindeki iş parçacıklarının listesi
Debugger.Models.Thread: İşlem içindeki tek bir iş parçacığı (kullanıcı veya çekirdek modundan bağımsız olarak)
Debugger.Models.Stack: İş parçacığı yığını
Debugger.Models.StackFrames: Yığın oluşturan çerçeve koleksiyonu
Debugger.Models.StackFrame: Yığın içinde tek bir yığın çerçevesi
Debugger.Models.LocalVariables: Yığın çerçevesi içindeki yerel değişkenler
Debugger.Models.Parameters: Yığın çerçevesindeki bir çağrının parametreleri
Debugger.Models.Module: İşlemin adres alanı içindeki tek bir modül
Ek Veri Modeli Nesneleri
Ayrıca, çekirdek veri modeli tarafından tanımlanan bazı ek veri modeli nesneleri vardır.
DataModel.Models.Intrinsic: İçsel değer (ordinal değerler, float değerler vb.)
DataModel.Models.String: Bir dize
DataModel.Models.Array: Yerel bir dizi
DataModel.Models.Guid: GUID
DataModel.Models.Error: Bir hata nesnesi
DataModel.Models.Concepts.Iterable: Yinelenebilir olan her nesneye uygulanır
DataModel.Models.Concepts.StringDisplayable: Görüntüleme dizesi dönüştürmesi olan her nesneye uygulanır
Örnek COM Hata Ayıklayıcısı Nesne Uzantısına Genel Bakış
Bir örnek düşünelim. Genel arabirim tablosu (GIT) gibi COM'a özgü bilgileri görüntülemek için bir hata ayıklayıcısı uzantısı oluşturmak istediğinizi düşünün.
Geçmişte, COM ile ilgili şeylere erişmek için bir araç sağlayan bir dizi komut içeren mevcut bir hata ayıklayıcı uzantısı olabilir. Bir komut işlem merkezli bilgileri (örneğin genel arabirim tablosu) görüntüleyebilir. Başka bir komut, hangi daire kodunun içinde yürütülmekte olduğu gibi iş parçacığı merkezli bilgiler sağlayabilir. COM'un diğer yönlerini keşfetmek için ikinci bir hata ayıklayıcısı uzantısını bilmeniz ve yüklemeniz gerekebilir.
JavaScript uzantısı, bulunması zor bir komut kümesine sahip olmak yerine hata ayıklayıcının işlem ve iş parçacığı kavramını değiştirerek bu bilgileri doğal, keşfedilebilir ve diğer hata ayıklayıcı uzantılarıyla birleştirilebilir bir şekilde ekleyebilir.
Kullanıcı veya Çekirdek Modu Hata Ayıklayıcısı Nesne Uzantısı
Hata ayıklayıcısı ve hata ayıklayıcı nesneleri, kullanıcı ve çekirdek modunda farklı davranışlara sahiptir. Hata ayıklayıcısı model nesnelerinizi oluştururken, hangi ortamlarda çalışacağınıza karar vermeniz gerekir. COM ile kullanıcı modunda çalışacağız çünkü bu com uzantısını kullanıcı modunda oluşturup test edeceğiz. Diğer durumlarda, hem kullanıcı hem de çekirdek modunda hata ayıklamada çalışacak bir hata ayıklayıcısı JavaScript oluşturabilirsiniz.
Alt Ad Alanı Oluşturma
Örneğimize geri dönüp, bir işlem nesnesine eklemek istediğimiz öğe kümesini içeren bir prototip veya ES6 sınıfı olan comProcessExtension tanımlayabiliriz.
Önemli Alt ad alanının amacı, mantıksal olarak yapılandırılmış ve doğal olarak keşfedilebilir bir paradigma oluşturmaktır. Örneğin, ilişkisiz öğelerin aynı alt ad alanına dökümünü kullanmaktan kaçının. Bir alt ad alanı oluşturmadan önce JavaScript Uzantılarındaki Yerel Hata Ayıklayıcı Nesneleri - Tasarım ve Test Konuları bölümünde açıklanan bilgileri dikkatle gözden geçirin.
Bu kod parçacığında mevcut işlem hata ayıklayıcısı nesnesine 'COM' adlı bir alt ad alanı ekliyoruz.
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);
}
}
Ad Alanı Uygulaması
Ardından, bir işlemde alt ad alanı COM'unu uygulayan nesneyi oluşturun.
Önemli Birden çok işlem olabilir (kullanıcı modunda veya KD altında bu işlemlere bağlı olabilir). Bu uzantı, hata ayıklayıcının mevcut durumunun kullanıcının hedeflediği durum olduğunu varsayamaz. Birisi <bazıProcess>.COM'u bir değişkende yakalayıp değiştirebilir ve bu da yanlış işlem bağlamından bilgi sunulmasına yol açabilir. Çözüm, uzantıya kod ekleyerek her örneklemenin hangi işleme eklendiğini izlemesini sağlamaktır. Bu kod örneği için bu bilgiler özelliğin 'this' işaretçisi aracılığıyla geçirilir.
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);
}
}
COM genel arabirim tablosu için uygulama mantığı
COM genel arabirim tablosunun uygulama mantığını daha net bir şekilde ayırmak için iki ES6 sınıfı tanımlayacağız: COM GIP tablosunu soyutlayan gipTable ve yukarıdaki Ad Alanı Uygulama kod parçacığında tanımlanan GlobalObjects() getter'ından döndürülecek olan globalObjects. Bu iç ayrıntıların hata ayıklayıcı ad alanında yayımlanmasını önlemek için bu ayrıntıların tümü initializeScript'in kapatılmasının içinde gizlenebilir.
// 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;
}
}
Son olarak, yeni COM işlevselliğini kaydetmek için host.namedModelRegistration kullanın.
function initializeScript()
{
return [new host.namedModelParent(comProcessExtension, "Debugger.Models.Process"),
new host.namedModelRegistration(comNamespace, "Debugger.Models.ComProcess")];
}
Not defteri gibi bir uygulama kullanarak kodu GipTableAbstractor.js için kaydedin.
Bu uzantıyı yüklemeden önce kullanıcı modunda kullanılabilen işlem bilgileri aşağıdadır.
0:000:x86> dx @$curprocess
@$curprocess : DataBinding.exe
Name : DataBinding.exe
Id : 0x1b9c
Threads
Modules
JavaScript uzantısını yükleyin.
0:000:x86> .scriptload C:\JSExtensions\GipTableAbstractor.js
JavaScript script successfully loaded from 'C:\JSExtensions\GipTableAbstractor.js'
Ardından önceden tanımlanmış @$curprocess kullanarak işlem hakkındaki bilgileri görüntülemek için dx komutunu kullanın.
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 *]
Bu tabloya GIT çerezi aracılığıyla programlı olarak da erişilebilir.
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]
LINQ ile Hata Ayıklayıcı Nesne Kavramlarını Genişletme
JavaScript, işlem ve iş parçacığı gibi nesneleri genişletebilmenin yanı sıra veri modeliyle ilişkili kavramları da genişletebilir. Örneğin, her yinelenebilir yönteme yeni bir LINQ yöntemi eklemek mümkündür. Her girdiyi yinelenebilir N kez çoğaltan "DuplicateDataModel" adlı örnek bir uzantıyı düşünün. Aşağıdaki kod, bunun nasıl uygulanabileceğini gösterir.
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")];
}
Not defteri gibi bir uygulama kullanarak kodu DuplicateDataModel.js için kaydedin.
Gerekirse JavaScript betik sağlayıcısını yükleyin ve ardından DuplicateDataModel.js uzantısını yükleyin.
0:000:x86> !load jsprovider.dll
0:000:x86> .scriptload C:\JSExtensions\DuplicateDataModel.js
JavaScript script successfully loaded from 'C:\JSExtensions\DuplicateDataModel.js'
Yeni Yinelenen işlevini test etmek için dx komutunu kullanın.
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)
…
Ayrıca bakınız
JavaScript Uzantılarında Yerel Hata Ayıklayıcı Nesneleri - Hata Ayıklayıcı Nesne Ayrıntıları
JavaScript Uzantılarında Yerel Hata Ayıklayıcı Nesneleri - Tasarım ve Test Konuları