
Usa Prolog per analizzare i dump di memoria e i processi live sospesi in WinDbg.
Un'estensione WinDbg nativa x64 e ARM64 con un worker SWI-Prolog persistente. Espone thread, stack frame, simboli, moduli caricati e memoria da un dump in modalità utente o da un processo nativo x64 o ARM64 arrestato. Carica i tuoi file Prolog ed esegui query dalla finestra dei comandi del debugger.
Version: 0.2.0 (experimental; native ARM64 support).
Usa la DLL compilata per l'architettura del tuo debugger. Il debugger, la DLL e
il target nativo devono corrispondere: x64/AMD64 insieme oppure ARM64 insieme. Contesti di scope
cross-architettura, WOW64, ARM32 e target ARM64EC sono al di fuori dello scope di questa release.
Le build native x64 e ARM64 hanno superato tutti i 99 controlli portabili e i test
smoke CDB su dump/live. Vedi docs/VALIDATION.md per l'esecuzione, i log e i controlli manuali rimanenti.
Il repository dei sorgenti non contiene binari compilati. Compilalo usando le
istruzioni per Windows riportate di seguito per popolare dist/x64/ o dist/arm64/. Gli archivi
di release sono denominati PrologWinDbg-v0.2.0-win-x64.zip e
PrologWinDbg-v0.2.0-win-arm64.zip; ciascuno colloca i binari selezionati in dist/.
Gli esempi seguenti usano quel layout dell'archivio di release. Per una build dai sorgenti,
sostituisci dist/arm64 o dist/x64 nei percorsi.
Installa la versione console per Windows di SWI-Prolog. Gli installer nativi ARM64 sono disponibili dai download di sviluppo. La matrice CI usa SWI-Prolog nativo 10.1.18-1 su entrambe le architetture. SWI viene eseguito come processo separato; non è collegato alla DLL né incluso in essa.
Mantieni dist/prolog.dll insieme
alle directory dist/prolog e dist/examples.
Apri un dump nativo in modalità utente nel WinDbg x64 o ARM64 corrispondente, oppure collega un processo nativo di quell'architettura e interrompilo. Per un dump riproducibile, esegui questo comando in PowerShell:
.\dist\prologdbg_target.exe --dump C:\Temp\prologdbg-sample.dmp
In WinDbg, sostituisci questi percorsi con la directory effettiva del tuo progetto. Usa le barre in avanti nei percorsi tra virgolette: il debugger interpreta le barre rovesciate come caratteri di escape.
.load C:/PrologWinDbg/dist/prolog.dll
!prolog.runtime "C:/Program Files/swipl/bin/swipl.exe"
!prolog.info
!prolog.consult "C:/PrologWinDbg/dist/examples/patterns.pl"
!prolog.query wd:current_snapshot(S), wd:architecture(S,Architecture).
!prolog.query wd:current_snapshot(S), wd:thread_id(S,T,WindowsTid).
!prolog.query wd:current_snapshot(S), wd:stack_frame(S,T,Depth,IP).
!prolog.query wd:current_snapshot(S), patterns:stack_contains(S,T,Module,Function).
L'estensione utilizza il percorso runtime esplicito, la variabile d'ambiente PROLOGDBG_SWIPL, oppure l'installazione standard Program Files\swipl\bin\swipl.exe.
Avvia il worker quando necessario per la prima volta. Tutta la comunicazione utilizza pipe locali.
Per il target fornito, ispezionare il marcatore noto di otto byte:
!prolog.query wd:current_snapshot(S), wd:lookup(S,'prologdbg_target!g_magic',ok(A)), patterns:inspect_magic(S,A,Verdict).
Verdetto atteso: matched(prologdb, Address). I byte del marker compongono
PROLOGDB. Il target esporta questi nomi, quindi questo esempio non richiede
un PDB. I PDB privati sono utili per altre funzioni e applicazioni.
Avvia prologdbg_target.exe --live sotto WinDbg. Prosegui oltre il breakpoint
iniziale del loader. Il target si ferma quindi a CapturePoint dopo che sono
stati avviati due thread worker. Usa le stesse query del caso di un dump.
In alternativa, esegui prologdbg_target.exe --wait, collegati al PID
stampato e interrompi l'esecuzione. Questa modalità termina dopo dieci minuti
se non viene fermata prima.
Usa i normali comandi WinDbg bp, g, p e t per controllare l'esecuzione.
Ogni !prolog.query raccoglie uno snapshot aggiornato. Le azioni dei breakpoint
Prolog registrate e la continuazione automatica sono previste per una versione
successiva.
| Comando | Scopo |
|---|---|
!prolog.help | Mostra la guida dei comandi |
!prolog.runtime "absolute path to swipl.exe" | Seleziona il runtime e arresta qualsiasi worker esistente |
!prolog.info | Avvia il worker e ne riporta la versione |
!prolog.consult "absolute path to rules.pl" | Carica o ricarica il sorgente Prolog |
!prolog.query Goal. | Raccoglie le evidenze ed enumera le soluzioni |
!prolog.queryfile "absolute path to goal.txt" | Legge un singolo goal UTF-8 da un file, quindi esegue la query |
!prolog.eval Goal. | Valuta Prolog senza evidenze del debugger |
!prolog.limits | Mostra i limiti correnti |
!prolog.limits 5000 100 128 10000000 | Imposta millisecondi, numero di risposte, frame per thread e limite di inferenze |
!prolog.reset | Arresta il worker; le regole caricate e lo stato del runtime personalizzato vengono persi |
I goal semplici vengono passati direttamente dopo il comando. Gli apici singoli
standard di Prolog delimitano gli atomi. Puoi omettere il punto finale. Usa un
goal per comando, unendo i sotto-goal con le virgole. Per la disgiunzione Prolog
(;), racchiudi l'intero goal tra virgolette doppie per proteggerlo dal
separatore di comandi di WinDbg:
!prolog.eval "(X=a;X=b), writeln(X)."
Per quoting complessi, testo Unicode o goal multilinea, inserisci il goal in un file di testo UTF-8 e usa !prolog.queryfile "C:/rules/goal.txt". Il suo contenuto va direttamente a Prolog, bypassando l'analisi del testo dei comandi di WinDbg. Il limite del file è 1 MiB. Per logica riutilizzabile, definisci i predicati in un file .pl consultato.
Esempio senza un target:
!prolog.eval member(X,[1,2,3]), Y is X*X.
Le risposte vengono stampate come bindings([Name=Value, ...], ResidualGoals). La seconda
lista conserva i vincoli residui. Uno stato finale distingue ricerca esaurita,
fallimento, limiti di risposte, limiti di inferenza, timeout ed eccezioni.
Raggiungere un limite di risposte non implica che esistano altre soluzioni.
La consultazione di un file esegue il normale caricamento e l'inizializzazione di Prolog. Gli errori di caricamento vengono segnalati, ma il caricamento di Prolog non è transazionale: alcune clausole possono essere state caricate prima di un errore. Correggere e ricaricare il file, oppure reimpostare il worker.
:- module(my_rules, [in_function/4]).
:- use_module('C:/PrologWinDbg/dist/prolog/wd.pl').
in_function(S, T, Module, Function) :-
wd:stack_frame(S, T, _, IP),
wd:symbol(S, IP, Module, Function, _).
Poi:
!prolog.consult "C:/rules/my_rules.pl"
!prolog.query wd:current_snapshot(S), my_rules:in_function(S,T,myapp,'ProcessRequest').
Consulta docs/API.md per le modalità dei predicati e la semantica delle evidenze. Le regole
iniziali forniscono la corrispondenza degli stack, le funzioni condivise tra i thread, l'evidenza
esplicita dello stack, gli indirizzi non leggibili e una diagnosi tramite firma di memoria con un
risultato inconcludente.
Il budget predefinito per le query è di 5 secondi, 100 risposte, 128 frame per thread e
10 milioni di inferenze. La raccolta degli snapshot riceve un proprio budget temporale della
stessa entità. Il caricamento iniziale dei simboli può essere lento: riscalda la cache dei simboli o
aumenta il primo valore con !prolog.limits.