Condividi tramite


Verifica dei simboli

I problemi dei simboli possono essere visualizzati in diversi modi. È possibile che un'analisi dello stack mostri informazioni errate o che non riesca a identificare i nomi delle funzioni nello stack. In alternativa, un comando del debugger non è riuscito a comprendere il nome di un modulo, una funzione, una variabile, una struttura o un tipo di dati.

Se si sospetta che il debugger non stia caricando correttamente i simboli, è possibile eseguire diversi passaggi per analizzare questo problema.

Usare prima di tutto il comando lm (List Loaded Modules) per visualizzare l'elenco dei moduli caricati con le informazioni sui simboli. La forma più utile di questo comando è la seguente:

0:000> lml 

Se si usa WinDbg, debug | Il comando di menu Moduli consentirà di visualizzare anche queste informazioni.

Prestare particolare attenzione a eventuali note o abbreviazioni che potrebbero essere visualizzate in questi schermi. Per un'interpretazione di queste informazioni, vedere Abbreviazioni dello stato dei simboli.

Se non vengono visualizzati i file di simboli appropriati, la prima cosa da fare consiste nel controllare il percorso del simbolo:

0:000> .sympath
Current Symbol Path is: d:\MyInstallation\i386\symbols\retail

Se il percorso del simbolo non è corretto, correggerlo. Se si usa il debugger del kernel, assicurarsi che %WINDIR% locale non si trovi nel percorso del simbolo.

Ricaricare quindi i simboli usando il comando .reload (Reload Module):

0:000> .reload ModuleName 

Se il percorso del simbolo è corretto, è consigliabile attivare la modalità rumorosa in modo da visualizzare i file di simboli che dbghelp sta caricando. Ricaricare quindi il modulo. Per informazioni su come attivare la modalità rumorosa, vedere Impostazione delle opzioni dei simboli.

Ecco un esempio di ricaricamento "rumoroso" dei simboli di Microsoft Windows:

kd> !sym noisy
kd> .reload nt
 1: Kernel Version 2081 MP Checked
 2: Kernel base = 0x80400000 PsLoadedModuleList = 0x80506fa0
 3: DBGHELP: FindExecutableImageEx-> Looking for D:\MyInstallation\i386\ntkrnlmp.exe...mismatched timestamp
 4: DBGHELP: No image file available for ntkrnlmp.exe
 5: DBGHELP: FindDebugInfoFileEx-> Looking for
 6: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.dbg... no file
 7: DBGHELP: FindDebugInfoFileEx-> Looking for
 8: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.pdb... no file
 9: DBGHELP: FindDebugInfoFileEx-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.dbg... OK
10: DBGHELP: LocatePDB-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.pdb... OK
11: *** WARNING: symbols checksum and timestamp is wrong 0x0036a4ea 0x00361a83 for ntkrnlmp.exe

Il gestore dei simboli cerca innanzitutto un'immagine corrispondente al modulo che sta tentando di caricare (righe tre e quattro). L'immagine stessa non è sempre necessaria, ma se ne è presente una non corretta, il gestore dei simboli avrà spesso esito negativo. Queste righe mostrano che il debugger ha trovato un'immagine in D:\MyInstallation\i386\ntkrnlmp.exe, ma il timestamp non corrisponde. Poiché il timestamp non corrisponde, la ricerca continua. Successivamente, il debugger cerca un file con estensione dbg e un file con estensione pdb che corrispondono all'immagine caricata. Si tratta di linee da 6 a 10. La riga 11 indica che, anche se i simboli sono stati caricati, l'indicatore di data e ora per l'immagine non corrisponde ,ovvero i simboli non sono stati eseguiti correttamente.

Se la ricerca di simboli ha rilevato un errore irreversibile, verrà visualizzato un messaggio del modulo:

ImgHlpFindDebugInfo(00000000, module.dll, c:\MyDir;c:\SomeDir, 0823345, 0) failed

Ciò può essere causato da elementi quali errori del file system, errori di rete e file con estensione dbg danneggiati.

Diagnosi degli errori di caricamento dei simboli

In modalità rumorosa, il debugger potrebbe stampare i codici di errore quando non è possibile caricare un file di simboli. I codici di errore per i file con estensione dbg sono elencati in winerror.h. I codici di errore con estensione pdb provengono da un'altra origine e gli errori più comuni vengono stampati in testo in inglese normale.

Alcuni codici di errore comuni per i file con estensione dbg di winerror.h sono:

0xB
ERROR_BAD_FORMAT

0x3
ERROR_PATH_NOT_FOUND

0x35
ERROR_BAD_NETPATH

È possibile che il file di simboli non possa essere caricato a causa di un errore di rete. Se vengono visualizzati ERROR_BAD_FORMAT o ERROR_BAD_NETPATH e si stanno caricando simboli da un altro computer in rete, provare a copiare il file di simboli nel computer host e inserire il relativo percorso nel percorso del simbolo. Provare quindi a ricaricare i simboli.

Verifica del percorso di ricerca e dei simboli

Let "c:\MyDir; c:\SomeDir" rappresentano il percorso del simbolo. Dove cercare le informazioni di debug?

Nei casi in cui il file binario è stato rimosso dalle informazioni di debug, ad esempio le build gratuite di Windows, cercare prima un file con estensione dbg nei percorsi seguenti:

c:\MyDir\symbols\exe\ntoskrnl.dbg
c:\SomeDir\symbols\exe\ntoskrnl.dbg
c:\MyDir\exe\ntoskrnl.dbg
c:\SomeDir\exe\ntoskrnl.dbg
c:\MyDir\ntoskrnl.dbg
c:\SomeDir\ntoskrnl.dbg
current-working-directory\ntoskrnl.dbg

Cercare quindi un file con estensione pdb nei percorsi seguenti:

c:\MyDir\symbols\exe\ntoskrnl.pdb
c:\MyDir\exe\ntoskrnl.pdb
c:\MyDir\ntoskrnl.pdb
c:\SomeDir\symbols\exe\ntoskrnl.pdb
c:\SomeDir\exe\ntoskrnl.pdb
c:\SomeDir\ntoskrnl.pdb
current-working-directory\ntoskrnl.pdb

Si noti che nella ricerca del file con estensione dbg, il debugger esegue la ricerca nelle directory MyDir e SomeDir, ma nella ricerca con estensione pdb non lo fa.

Windows XP e versioni successive di Windows non usano file di simboli con estensione dbg. Per informazioni dettagliate , vedere Simboli e file di simboli .

Compilazioni non corrispondenti

Uno dei problemi più comuni relativi agli errori di debug in un computer che viene spesso aggiornato non corrisponde ai simboli provenienti da compilazioni diverse. Tre cause comuni di questo problema sono: puntando ai simboli per la compilazione errata, usando un file binario compilato privatamente senza i simboli corrispondenti e usando il livello di astrazione hardware uniprocessore (HAL) e i simboli del kernel in un computer multiprocessore. I primi due sono semplicemente una questione di corrispondenza tra i file binari e i simboli; il terzo può essere corretto rinominando hal*.dbg e ntkrnlmp.dbg a hal.dbg e ntoskrnl.dbg.

Per scoprire la build di Windows installata nel computer di destinazione, usare il comando vertarget (Mostra versione computer di destinazione):

kd> vertarget 
Windows XP Kernel Version 2505 UP Free x86 compatible
Built by: 2505.main.010626-1514
Kernel base = 0x804d0000 PsLoadedModuleList = 0x80548748
Debug session time: Mon Jul 02 14:41:11 2001
System Uptime: 0 days 0:04:53 

Test dei simboli

Testare i simboli è più difficile. Implica la verifica di un'analisi dello stack nel debugger e la verifica se l'output di debug è corretto. Ecco un esempio da provare:

kd> u videoprt!videoportfindadapter2
Loading symbols for 0xf2860000     videoprt.sys ->   videoprt.sys

VIDEOPRT!VideoPortFindAdapter2:
f2856f42 55               push    ebp
f2856f43 8bec             mov     ebp,esp
f2856f45 81ecb8010000     sub     esp,0x1b8
f2856f4b 8b4518           mov     eax,[ebp+0x18]
f2856f4e 53               push    ebx
f2856f4f 8365f400         and     dword ptr [ebp-0xc],0x
f2856f53 8065ff00         and     byte ptr [ebp-0x1],0x0
f2856f57 56               push    esi

Il comando u separa la stringa videoportfindadapter in videoprt.sys. I simboli sono corretti nel debugger perché i comandi stack comuni, ad esempio push e mov , vengono visualizzati nello stack. La maggior parte delle funzioni inizia con un'operazione add, sub o push usando il puntatore di base (ebp) o il puntatore dello stack (esp).

Di solito è ovvio quando i simboli non funzionano correttamente. Glintmp.sys non ha simboli in questo esempio perché una funzione non è elencata accanto a Glintmp:

kd> kb
Loading symbols for 0xf28d0000     videoprt.sys ->   videoprt.sys
Loading symbols for 0xf9cdd000      glintmp.sys ->   glintmp.sys
*** ERROR: Symbols could not be loaded for glintmp.sys
ChildEBP RetAddr  Args to Child
f29bf1b0 8045b5fa 00000001 0000a100 00000030 ntoskrnl!RtlpBreakWithStatusInstruction
f29bf1b0 8044904e 00000001 0000a100 00000030 ntoskrnl!KeUpdateSystemTime+0x13e
f29bf234 f28d1955 f9b7d000 ffafb2dc f9b7d000 ntoskrnl!READ_REGISTER_ULONG+0x6
f29bf248 f9cde411 f9b7d000 f29bf2b0 f9ba0060 VIDEOPRT!VideoPortReadRegisterUlong+0x27
00000002 00000000 00000000 00000000 00000000 glintMP+0x1411 [No function listed.] 

I simboli di compilazione errati sono stati caricati per questa analisi dello stack. Si noti che non sono elencate funzioni per le prime due chiamate. L'analisi dello stack è simile a un problema con win32k.sys rettangoli di disegno:

1: kd> 
1: kd> kb                      [Local        9:50 AM]
Loading symbols for 0xf22b0000       agpcpq.sys ->   agpcpq.sys
*** WARNING: symbols checksum is wrong 0x0000735a 0x00000000 for agpcpq.sys
*** ERROR: Symbols could not be loaded for agpcpq.sys
Loading symbols for 0xa0000000       win32k.sys ->   win32k.sys
*** WARNING: symbols checksum is wrong 0x00191a41 0x001995a9 for win32k.sys
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ+0x125b [No function listed.]
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 agpCPQ+0x372b [No function listed.]
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!vPatCpyRect1_6x6+0x20b
00000001 00000000 00000000 00000000 00000000 win32k!RemoteRedrawRectangle+0x32 

Ecco l'analisi dello stack corretta. Il problema è proprio con AGP440.sys. Il primo elemento visualizzato in un'analisi dello stack è in genere in errore. Si noti che l'errore del rettangolo di win32k.sys non è più presente:

1: kd> kb                      [Local        9:49 AM]
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ!AgpReleaseMemory+0x88
be682b30 f20a385c 82703638 e183ec68 00000000 agpCPQ!AgpInterfaceReleaseMemory+0x8b
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 VIDEOPRT!AgpReleasePhysical+0x44
be682b58 a0139605 e1cee560 e11410a8 a00e5f0a win32k!OsAGPFree+0x14
be682b64 a00e5f0a e1cee560 e11410a8 e1cee560 win32k!AGPFree+0xd
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!HeapVidMemFini+0x49
be682b9c a00f5c20 e1cee008 e1cee008 be682c0c win32k!vDdDisableDriver+0x3a
be682bac a00da510 e1cee008 00000000 be682c0c win32k!vDdDisableDirectDraw+0x2d
be682bc4 a00da787 00000000 e1843df8 e1843de8 win32k!PDEVOBJ__vDisableSurface+0x27
be682bec a00d59fb 00000000 e1843de8 00000000 win32k!PDEVOBJ__vUnreferencePdev+0x204
be682c04 a00d7421 e1cee008 82566a98 00000001 win32k!DrvDestroyMDEV+0x30
be682ce0 a00a9e7f e1843e10 e184a008 00000000 win32k!DrvChangeDisplaySettings+0x8b3
be682d20 a008b543 00000000 00000000 00000000 win32k!xxxUserChangeDisplaySettings+0x106
be682d48 8045d119 00000000 00000000 00000000 win32k!NtUserChangeDisplaySettings+0x48
be682d48 77e63660 00000000 00000000 00000000 ntkrnlmp!KiSystemService+0xc9 

Comandi ed estensioni utili

I comandi e le estensioni seguenti possono essere utili per tenere traccia dei problemi relativi ai simboli:

lm (elencare i moduli caricati)
Elenca tutti i moduli e fornisce lo stato di caricamento di tutti i simboli in questi moduli.

!dh image-header-base
Visualizza le informazioni di intestazione per un'immagine caricata a partire da image-header-base.

.reload /n
Ricarica tutti i simboli del kernel.

.reload [image-name]
(solo CDB o WinDbg) Ricarica i simboli per il nome dell'immagine. Se non viene specificato alcun nome di immagine , ricarica i simboli per tutte le immagini. È necessario ricaricare i simboli dopo la modifica del percorso del simbolo.

!sym rumoroso
Attiva la modalità dettagliata per il caricamento dei simboli. Può essere usato per ottenere informazioni sul caricamento del modulo. Per informazioni dettagliate, vedere Impostazione delle opzioni dei simboli .

.sympath [new-symbol-path]
Imposta un nuovo percorso simbolo o visualizza il percorso del simbolo corrente. Per informazioni dettagliate, vedere Percorso dei simboli .

Se i simboli del kernel sono corretti, ma non si ottiene uno stack completo, possono essere utili anche i comandi seguenti:

X*!
Verranno elencati i moduli in cui sono attualmente caricati i simboli. Ciò è utile se i simboli del kernel sono corretti.

.reload /user
In questo modo si tenterà di ricaricare tutti i simboli in modalità utente. Questa operazione è necessaria durante l'esecuzione del debug del kernel se i simboli sono stati caricati durante l'esecuzione di un processo e un'interruzione successivamente si è verificata in un altro processo. In questo caso, i simboli in modalità utente del nuovo processo non verranno caricati a meno che non venga eseguito questo comando.

X wdmaud!*start\*
Verranno elencati solo i simboli nel modulo wdmaud i cui nomi contengono la stringa "start". Questo ha il vantaggio che forza il ricaricamento di tutti i simboli in wdmaud, ma visualizza solo quelli con "start" in essi. Questo significa un elenco più breve, ma poiché ci sono sempre alcuni simboli con "inizio" in essi, ci sarà una verifica che il carico sia stato eseguito.

Un'altra tecnica utile per verificare i simboli è il codice di unassembling. La maggior parte delle funzioni inizia con un'operazione add, sub o push usando il puntatore di base (ebp) o il puntatore dello stack (esp o sp). Provare a separare (U Function) alcune delle funzioni nello stack (dall'offset zero) per verificare i simboli.

Problemi di rete e porta

Si verificheranno problemi con i file di simboli e durante la connessione al debugger. Ecco alcuni aspetti da tenere presenti se si verificano problemi:

  • Determinare la porta COM a cui è connesso il cavo di debug nel sistema di test.

  • Controllare le impostazioni boot.ini del sistema di test. Cercare l'opzione /debug e controllare le impostazioni di velocità in baud e porta COM.

  • I problemi di rete possono interferire con il debug se si accede ai file di simboli tramite la rete.

  • .dll e .sys file con lo stesso nome (ad esempio , − mga64.sys e mga64.dll) confondono il debugger se non sono separati nelle directory appropriate dell'albero dei simboli.

  • Il debugger del kernel non è sempre simile alla sostituzione dei file di simboli di compilazione con file di simboli privati. Controllare il percorso del simbolo ed eseguire un filename con estensione reload sul simbolo di comportamento errato. Il comando !dlls è talvolta utile.

Domande e malintesi

D: I simboli sono stati caricati correttamente, ma lo stack sembra essere sbagliato. Il debugger è interrotto?

Un: Non necessariamente. La causa più probabile del problema è che sono presenti simboli non corretti. Seguire i passaggi descritti in questa sezione per determinare se sono stati caricati o meno simboli validi. Non presupporre che perché alcune cose funzionano con simboli validi. Ad esempio, è possibile eseguire dd nt!ntbuildnumber o u nt nt! KeInitializeProcess con simboli non corretti. Verificare che siano corretti usando le procedure descritte in precedenza.

D: Il debugger continuerà a funzionare con simboli non corretti?

Un: Sì e no. Spesso è possibile uscire con simboli che non corrispondono strettamente. Ad esempio, i simboli di una build di Windows precedente funzionano spesso in determinati casi, ma non esiste alcuna regola per quando funzionerà e quando non funzionerà.

D: Il debugger del kernel viene arrestato e si desidera visualizzare i simboli per il processo in modalità utente. Posso farlo?

Un: Principalmente. Il supporto per questo scenario è scarso perché il debugger del kernel non mantiene informazioni sufficienti per tenere traccia dei caricamenti del modulo per ogni processo, ma esiste una soluzione ragionevole. Per caricare i simboli per un modulo in modalità utente, eseguire un comando .reload -user . Verranno caricati i moduli in modalità utente per il contesto corrente.

D: Cosa significa il messaggio seguente?

*** WARNING: symbols checksum and timestamp is wrong 0x0036d6bf 0x0036ab55 for ntkrnlmp.exe

Un: Significa che i simboli per ntkrnlmp.exe sono sbagliati.