Verificando símbolos

Problemas de símbolo podem aparecer de várias maneiras. Talvez um rastreamento de pilha mostre informações incorretas ou não identifique os nomes das funções na pilha. Ou talvez um comando de depurador não tenha entendido o nome de um módulo, função, variável, estrutura ou tipo de dados.

Se você suspeitar que o depurador não está carregando símbolos corretamente, há várias etapas que você pode executar para investigar esse problema.

Primeiro, use o comando lm (List Loaded Modules) para exibir a lista de módulos carregados com informações de símbolo. A forma mais útil deste comando é a seguinte:

0:000> lml 

Se você estiver usando o WinDbg, o Depurar | O comando de menu Módulos também permitirá que você veja essas informações.

Preste atenção especial a quaisquer anotações ou abreviações que você possa ver nessas exibições. Para obter uma interpretação dessas, consulte Abreviações de Status do Símbolo.

Se você não vir os arquivos de símbolo adequados, a primeira coisa a fazer é marcar o caminho do símbolo:

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

Se o caminho do símbolo estiver errado, corrija-o. Se você estiver usando o depurador de kernel, verifique se o %WINDIR% local não está no caminho do símbolo.

Em seguida, recarregue os símbolos usando o comando .reload (Módulo recarregar ):

0:000> .reload ModuleName 

Se o caminho do símbolo estiver correto, você deverá ativar o modo barulhento para poder ver quais arquivos de símbolo dbghelp está carregando. Em seguida, recarregue o módulo. Consulte Configurando opções de símbolo para obter informações sobre como ativar o modo barulhento.

Aqui está um exemplo de um recarregamento "barulhento" dos símbolos do 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

O manipulador de símbolos procura primeiro uma imagem que corresponda ao módulo que está tentando carregar (linhas três e quatro). A imagem em si nem sempre é necessária, mas se uma incorreta estiver presente, o manipulador de símbolos geralmente falhará. Essas linhas mostram que o depurador encontrou uma imagem em D:\MyInstallation\i386\ntkrnlmp.exe, mas o carimbo de data/hora não correspondeu. Como o carimbo de data/hora não correspondeu, a pesquisa continua. Em seguida, o depurador procura um arquivo .dbg e um arquivo .pdb que correspondam à imagem carregada. Elas estão nas linhas 6 a 10. A linha 11 indica que, embora os símbolos tenham sido carregados, o carimbo de data/hora da imagem não correspondeu (ou seja, os símbolos estavam errados).

Se a pesquisa de símbolos encontrou uma falha catastrófica, você verá uma mensagem do formulário:

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

Isso pode ser causado por itens como falhas do sistema de arquivos, erros de rede e arquivos .dbg corrompidos.

Diagnosticando erros de carregamento de símbolo

Quando estiver no modo barulhento, o depurador poderá imprimir códigos de erro quando não puder carregar um arquivo de símbolo. Os códigos de erro para arquivos .dbg são listados em winerror.h. Os códigos de erro .pdb vêm de outra origem e os erros mais comuns são impressos em texto em inglês sem formatação.

Alguns códigos de erro comuns para arquivos .dbg de winerror.h são:

0xB
ERROR_BAD_FORMAT

0x3
ERROR_PATH_NOT_FOUND

0x35
ERROR_BAD_NETPATH

É possível que o arquivo de símbolo não possa ser carregado devido a um erro de rede. Se você vir ERROR_BAD_FORMAT ou ERROR_BAD_NETPATH e estiver carregando símbolos de outro computador na rede, tente copiar o arquivo de símbolo para o computador host e coloque seu caminho no caminho do símbolo. Em seguida, tente recarregar os símbolos.

Verificando seu caminho de pesquisa e símbolos

Deixe "c:\MyDir; c:\SomeDir" representa o caminho do símbolo. Onde você deve procurar informações de depuração?

Nos casos em que o binário foi removido de informações de depuração, como os builds gratuitos do Windows, primeiro procure um arquivo .dbg nos seguintes locais:

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

Em seguida, procure um arquivo .pdb nos seguintes locais:

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

Observe que, na pesquisa do arquivo .dbg, o depurador intercala a pesquisa pelos diretórios MyDir e SomeDir, mas na pesquisa .pdb não.

O Windows XP e versões posteriores do Windows não usam nenhum arquivo de símbolo .dbg. Consulte Símbolos e Arquivos de Símbolos para obter detalhes.

Builds incompatíveis

Um dos problemas mais comuns na depuração de falhas em um computador que geralmente é atualizado são símbolos incompatíveis de builds diferentes. Três causas comuns desse problema são: apontar para símbolos para o build errado, usar um binário criado de forma privada sem os símbolos correspondentes e usar o HAL (nível de abstração de hardware) uniprocessador e símbolos de kernel em um computador multiprocessador. Os dois primeiros são simplesmente uma questão de corresponder seus binários e símbolos; o terceiro pode ser corrigido renomeando hal*.dbg e ntkrnlmp.dbg para hal.dbg e ntoskrnl.dbg.

Para descobrir qual build do Windows está instalado no computador de destino, use o comando vertarget (Mostrar Versão do Computador de Destino):

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 

Testando os símbolos

Testar os símbolos é mais difícil. Isso envolve verificar um rastreamento de pilha no depurador e ver se a saída de depuração está correta. Aqui está um exemplo para tentar:

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

O comando u desmonta a cadeia de caracteres videoportfindadapter em videoprt.sys. Os símbolos estão corretos no depurador porque comandos comuns de pilha, como push e mov , aparecem na pilha. A maioria das funções começa com uma operação add, sub ou push usando o ponteiro base (ebp) ou o ponteiro de pilha (esp).

Geralmente, é óbvio quando os símbolos não estão funcionando corretamente. Glintmp.sys não tem símbolos neste exemplo porque uma função não está listada ao lado de 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.] 

Os símbolos de build errados foram carregados para esse rastreamento de pilha. Observe como não há funções listadas para as duas primeiras chamadas. Esse rastreamento de pilha parece um problema com retângulos de desenho win32k.sys:

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 

Aqui está o rastreamento de pilha correto. O problema é realmente com AGP440.sys. O primeiro item que aparece em um rastreamento de pilha geralmente está em falha. Observe que o erro win32k.sys retângulo desapareceu:

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 

Comandos e extensões úteis

Os seguintes comandos e extensões podem ser úteis para rastrear problemas de símbolo:

lm (Listar Módulos Carregados)
Lista todos os módulos e fornece a status de carregamento de todos os símbolos nesses módulos.

!dh image-header-base
Exibe informações de cabeçalho para uma imagem carregada começando em image-header-base.

.reload /n
Recarrega todos os símbolos de kernel.

.reload [image-name]
(Somente CDB ou WinDbg) Recarrega símbolos para o nome da imagem. Se nenhum nome de imagem for especificado, recarregue os símbolos para todas as imagens. (É necessário recarregar símbolos depois que o caminho do símbolo for alterado.)

!sym barulhento
Ativa o modo detalhado para cargas de símbolo. Isso pode ser usado para obter informações sobre as cargas do módulo. Consulte Configurando opções de símbolo para obter detalhes.

.sympath [new-symbol-path]
Define um novo caminho de símbolo ou exibe o caminho do símbolo atual. Confira Caminho do Símbolo para obter detalhes.

Se os símbolos de kernel estiverem corretos, mas você não estiver recebendo uma pilha completa, os seguintes comandos também poderão ser úteis:

X*!
Isso listará os módulos que atualmente têm símbolos carregados. Isso será útil se os símbolos de kernel estiverem corretos.

.reload /user
Isso tentará recarregar todos os símbolos do modo de usuário. Isso é necessário ao executar a depuração de kernel se os símbolos foram carregados enquanto um processo estava em execução e uma interrupção ocorreu posteriormente em outro processo. Nesse caso, os símbolos do modo de usuário do novo processo não serão carregados, a menos que esse comando seja executado.

X wdmaud!*start\*
Isso listará apenas os símbolos no módulo wdmaud cujos nomes contêm a cadeia de caracteres "start". Isso tem a vantagem de forçar o recarregamento de todos os símbolos no wdmaud, mas exibe apenas aqueles com "start" neles. (Isso significa uma listagem mais curta, mas como há sempre alguns símbolos com "start" neles, haverá alguma verificação de que a carga ocorreu.)

Uma outra técnica útil para verificar símbolos é a desmontagem de código. A maioria das funções começa com uma operação add, sub ou push usando o ponteiro base (ebp) ou o ponteiro de pilha (esp ou sp). Tente desmontar (Função U) algumas das funções na pilha (do deslocamento zero) para verificar os símbolos.

Problemas de rede e porta

Problemas ocorrerão com os arquivos de símbolo e durante a conexão com o depurador. Aqui estão algumas coisas a ter em mente se você encontrar problemas:

  • Determine a qual porta COM o cabo de depuração está conectado no sistema de teste.

  • Verifique as configurações de boot.ini do sistema de teste. Procure a opção /debug e marcar a taxa de baud e as configurações da porta COM.

  • Problemas de rede podem interferir na depuração se os arquivos de símbolos forem acessados por meio da rede.

  • .dll e arquivos .sys com o mesmo nome (por exemplo , mga64.sys e mga64.dll) confundirão o depurador se eles não estiverem separados nos diretórios adequados da árvore de símbolos.

  • O depurador de kernel nem sempre gosta de substituir os arquivos de símbolo de build por arquivos de símbolo privados. Marcar o caminho do símbolo e faça um .reloadFileName no símbolo mal comportado. Às vezes, o comando !dlls é útil.

Perguntas e equívocos

Q: Carreguei símbolos com êxito, mas a pilha parece estar errada. O depurador está quebrado?

Um: Não necessariamente. A causa mais provável do problema é que você tem símbolos incorretos. Siga as etapas descritas nesta seção para determinar se você carregou símbolos válidos ou não. Não suponha que, como algumas coisas funcionam, você tem símbolos válidos. Por exemplo, você pode muito bem ser capaz de executar dd nt!ntbuildnumber ou u nt! KeInitializeProcess com símbolos incorretos. Verifique se eles estão corretos usando os procedimentos descritos acima.

Q: O depurador ainda funcionará com símbolos incorretos?

Um: Sim e não. Muitas vezes, você pode se safar de símbolos que não correspondem estritamente. Por exemplo, símbolos de um build anterior do Windows geralmente funcionarão em determinados casos, mas não há nenhuma regra sobre quando isso funcionará e quando não funcionará.

Q: Estou parado no depurador de kernel e quero exibir símbolos para o meu processo de modo de usuário. Posso fazer isso?

Um: Principalmente. O suporte para esse cenário é ruim porque o depurador de kernel não mantém informações suficientes para acompanhar as cargas do módulo para cada processo, mas há uma solução alternativa razoável. Para carregar símbolos para um módulo de modo de usuário, execute um comando .reload -user . Isso carregará os módulos do modo de usuário para o contexto atual.

Q: O que significa a mensagem a seguir?

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

Um: Significa que seus símbolos para ntkrnlmp.exe estão errados.