Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A TTD (Depuração Temporal) permite que os usuários registrem rastros, que são gravações da execução de um programa. Linhas do tempo são uma representação visual de eventos que ocorrem durante a execução. Esses eventos podem ser locais de pontos de interrupção, leituras/gravações de memória, chamadas e retornos de função e exceções.
Use a janela Linhas do Tempo para exibir eventos importantes, entender sua posição relativa e ir facilmente para o local em seu arquivo de rastreamento TTD. Use várias linhas do tempo para explorar visualmente eventos no rastreamento de viagem no tempo e descobrir a correlação de eventos.
A janela Linhas do Tempo é exibida quando você abre um arquivo de rastreamento TTD. Ele mostra os principais eventos sem que você precise criar consultas de modelo de dados manualmente. Ao mesmo tempo, todos os objetos de viagem no tempo estão disponíveis para permitir consultas de dados mais complexas.
Para obter mais informações sobre como criar e trabalhar com arquivos de rastreamento de viagem no tempo, consulte Depuração de Viagem no Tempo: Visão geral.
Tipos de linhas do tempo
A janela Linhas do Tempo mostra eventos nas seguintes linhas do tempo:
- Exceções: você pode filtrar em um código de exceção específico.
- Pontos de interrupção: você pode ver quando pontos de interrupção atingem uma linha do tempo.
- Acessos de memória: você pode ler, gravar e executar entre dois endereços de memória.
-
Chamadas de função: você pode pesquisar na forma de
module!function.
Passe o mouse sobre cada evento para obter mais informações por meio da dica de ferramenta. Selecionar um evento executa a consulta do evento e exibe mais informações. Clicar duas vezes em um evento salta para esse local no arquivo de rastreamento TTD.
Exceções
Quando você carrega um arquivo de rastreamento e a linha do tempo está ativa, ele exibe todas as exceções na gravação automaticamente.
Quando você passa o mouse sobre um ponto de interrupção, informações como o tipo de exceção e o código de exceção são exibidas.
Você pode filtrar ainda mais em um código de exceção específico usando o campo Código de Exceção opcional.
Você também pode adicionar uma nova linha do tempo para um tipo de exceção específico.
Pontos de interrupção
Depois de adicionar um ponto de interrupção, as posições na linha do tempo mostram quando esse ponto de interrupção é atingido. Por exemplo, você pode usar o comando bp Set Breakpoint. Quando você passa o mouse sobre um ponto de interrupção, o endereço e o ponteiro de instrução associados ao ponto de interrupção são exibidos.
Quando o ponto de interrupção é limpo, a linha do tempo do ponto de interrupção associada é removida automaticamente.
Chamadas de função
Você pode ver as posições das chamadas de função na linha do tempo. Para fazer essa etapa, forneça a pesquisa na forma de module!function. Um exemplo é TimelineTestCode!multiplyTwo. Você também pode especificar 'wildcards', por exemplo, TimelineTestCode!m*.
Quando você passa o mouse sobre uma chamada de função, o nome da função, os parâmetros de entrada, seus valores e o valor retornado são exibidos. Este exemplo mostra o buffer e o tamanho porque eles são os parâmetros para DisplayGreeting!GetCppConGreeting.
Acesso à memória
Use a linha do tempo de Acessos de Memória para ver quando um intervalo específico de memória foi lido ou gravado ou em que local ocorreu a execução do código. Os endereços iniciar e parar são usados para definir um intervalo entre dois endereços de memória.
Quando você passa o mouse sobre um item de acesso à memória, o valor e o ponteiro de instrução são exibidos.
Trabalhar com linhas do tempo
Uma linha cinza vertical segue o cursor quando você passa o mouse sobre a linha do tempo. A linha azul vertical indica a posição atual no rastreamento.
Selecione os ícones de lupa para ampliar e reduzir a linha do tempo.
Na área de controle superior da linha do tempo, use o retângulo para mover a visão da linha do tempo. Arraste os delimitadores externos do retângulo para redimensionar a exibição da linha do tempo atual.
Movimentos do mouse
Para ampliar e reduzir, selecione Ctrl e use a roda de rolagem.
Para mover lateralmente, selecione a tecla Shift e use a roda de rolagem.
Técnicas de depuração da linha do tempo
Para demonstrar técnicas de depuração com linha do tempo, o passo a passo de Depuração de Viagem no Tempo é reutilizado aqui. Essa demonstração pressupõe que você concluiu as duas primeiras etapas para criar o código de exemplo e criou a gravação TTD usando as duas primeiras etapas descritas lá.
Nesse cenário, a primeira etapa é encontrar a exceção no rastreio de viagem no tempo. Clique duas vezes na única exceção que você vê na linha do tempo.
Na janela Comando , você pode ver que o comando a seguir foi emitido quando você selecionou a exceção.
(2dcc.6600): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: CC:0
@$curprocess.TTD.Events.Where(t => t.Type == "Exception")[0x0].Position.SeekTo()
Selecione Exibir>Registros para exibir os registros neste ponto na linha do tempo para iniciar sua investigação.
Na saída do comando, a pilha (esp) e o ponteiro base (ebp) estão apontando para endereços diferentes. Essa discrepância pode indicar corrupção na pilha. Possivelmente, uma função retornou e corrompeu a pilha. Para validar esse problema, volte para um momento antes do estado da CPU ser corrompido e verifique se é possível determinar quando a corrupção da pilha ocorreu.
Ao fazer esse processo, examine os valores das variáveis locais e da pilha:
- Selecione Exibir>Locais para exibir os valores locais.
- Selecione Exibir>Pilha para exibir a pilha de execução de código.
No momento da falha, é comum que o rastreamento termine algumas etapas depois da verdadeira causa no código de tratamento de erros. Utilizando a viagem no tempo, você pode voltar uma instrução de cada vez para identificar a verdadeira causa raiz.
Na faixa de opções Página Inicial , use o comando Step Into Back para recuar três instruções. À medida que você faz esse processo, continue examinando as janelas Stack, Locals e Registers.
A janela Comando exibe a posição da viagem no tempo e os registros à medida que você retrocede três instruções anteriores.
0:000> t-
Time Travel Position: CB:41
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00540020 esp=003cf7d0 ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
00540020 ?? ???
0:000> t-
Time Travel Position: CB:40
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00061767 esp=003cf7cc ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
DisplayGreeting!main+0x57:
00061767 c3 ret
0:000> t-
Time Travel Position: CB:3A
eax=0000004c ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=0006175f esp=003cf718 ebp=003cf7c8 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
DisplayGreeting!main+0x4f:
0006175f 33c0 xor eax,eax
Neste ponto do rastreamento, sua pilha e o ponteiro base têm valores que fazem mais sentido. Parece que você está se aproximando do ponto no código em que a corrupção ocorreu.
esp=003cf718 ebp=003cf7c8
A janela Locals contém valores de seu aplicativo de destino. A janela código-fonte realça a linha de código que está pronta para ser executada no código-fonte neste ponto do rastreamento.
Para investigar mais a fundo, abra uma janela Memória para visualizar o conteúdo próximo ao endereço de memória do ponteiro de pilha (esp). Neste exemplo, ele tem um valor de 003cf7c8. Selecione Memória>Texto>ASCII para exibir o texto ASCII armazenado nesse endereço.
Linha do tempo de acesso à memória
Depois que um local de interesse de memória for identificado, use esse valor para adicionar uma linha do tempo de acesso à memória. Selecione + Adicionar linha do tempo e preencha o endereço inicial. Examine 4 bytes para que, ao adicioná-los ao valor de Endereço Inicial, 003cf7c8você tenha um valor de Endereço Final.003cf7cb O padrão é examinar todas as gravações de memória, mas você também pode examinar apenas gravações ou execução de código nesse endereço.
Agora você pode percorrer a linha do tempo ao contrário para examinar em que ponto neste rastreamento de viagem de tempo esse local de memória foi gravado para ver o que você pode encontrar. Ao selecionar essa posição na linha do tempo, você pode ver que os locais valorizam valores diferentes para a cadeia de caracteres que está sendo copiada. O valor de destino parece estar incompleto, como se o comprimento da cadeia de caracteres não estivesse correto.
Linha do tempo do ponto de interrupção
Usar pontos de interrupção é uma abordagem comum para pausar a execução de código em algum evento de interesse. Com o TTD, você pode definir um ponto de interrupção e retornar no tempo até que esse ponto de interrupção seja alcançado após o rastreamento ser gravado. A capacidade de examinar o estado do processo após um problema, determinar o melhor local para um ponto de interrupção, permite mais fluxos de trabalho de depuração exclusivos para TTD.
Para explorar uma técnica alternativa de depuração da linha do tempo, selecione a exceção na linha do tempo e, mais uma vez, retorne três etapas usando o comando Step Into Back na faixa de opções Home .
Neste pequeno exemplo, é fácil procurar no código. Se você tiver centenas de linhas de código e dezenas de sub-rotinas, use as técnicas descritas aqui para diminuir o tempo necessário para localizar o problema.
Conforme mencionado anteriormente, o ponteiro base (esp) aponta para o texto da mensagem em vez de apontar para uma instrução.
Use o ba comando para definir um ponto de interrupção no acesso à memória. Você define um w - ponto de interrupção de gravação para ver quando essa área de memória é gravada.
0:000> ba w4 003cf7c8
Embora você use um ponto de interrupção de acesso à memória simples, você pode construir pontos de interrupção para serem instruções condicionais mais complexas. Para obter mais informações, consulte bp, bu, bm (Definir ponto de interrupção).
No menu Página Inicial , selecione Voltar para viajar de volta no tempo até que o ponto de interrupção seja atingido.
Neste ponto, você pode examinar a pilha de programas para ver qual código está ativo.
Como é improvável que a função fornecida pela wscpy_s() Microsoft possa ter um bug de código como este, verifique mais detalhadamente a pilha de chamadas. A pilha mostra que Greeting!main chama Greeting!GetCppConGreeting. No seu pequeno exemplo de código, você pode abrir o código neste momento e provavelmente encontrar o erro facilmente. Mas para ilustrar as técnicas que você pode usar com um programa maior e mais complexo, adicione uma linha do tempo de chamada de função.
Linha do tempo da chamada de função
Selecione + Adicionar linha do tempo e preencha DisplayGreeting!GetCppConGreeting a cadeia de caracteres de pesquisa de função.
Os checkboxes Local de Início e Local de Término indicam o início e o fim de uma chamada de função no rastreamento.
Você pode usar o dx comando para exibir o objeto de chamada de função para ver os campos associados TimeStart e TimeEnd que correspondem ao local de início e ao local de término da chamada de função.
dx @$cursession.TTD.Calls("DisplayGreeting!GetCppConGreeting")[0x0]
EventType : 0x0
ThreadId : 0x6600
UniqueThreadId : 0x2
TimeStart : 6D:BD [Time Travel]
SystemTimeStart : Thursday, October 31, 2019 23:36:05
TimeEnd : 6D:742 [Time Travel]
SystemTimeEnd : Thursday, October 31, 2019 23:36:05
Function : DisplayGreeting!GetCppConGreeting
FunctionAddress : 0x615a0
ReturnAddress : 0x61746
Parameters
Uma das caixas de seleção Local de Início ou Local de Término ou ambas as caixas de seleção Local de Início e Local de Término devem ser selecionadas.
Seu código não é recursivo ou reentrante, portanto, é fácil localizar quando o método GetCppConGreeting é chamado na linha do tempo. A chamada para GetCppConGreeting também ocorre ao mesmo tempo que o seu ponto de interrupção e o evento de acesso à memória que você definiu. Portanto, parece que você restringiu uma área de código para examinar cuidadosamente a causa raiz da falha do aplicativo.
Explorar a execução de código exibindo várias linhas do tempo
Embora nosso exemplo de código seja pequeno, a técnica de usar várias linhas do tempo permite a exploração visual de um rastreamento de viagem no tempo. Você pode procurar o arquivo de rastreamento para fazer perguntas, como "Quando uma área de memória é acessada antes de um ponto de interrupção ser atingido?".
A capacidade de ver mais correlações e encontrar coisas inesperadas diferencia a ferramenta de linha do tempo de interagir com o rastreamento de viagem no tempo usando comandos de linha de comando.
Marcadores de cronograma
Marque posições importantes de viagem pelo tempo no WinDbg ao invés de copiar e colar manualmente a posição no Bloco de Notas. Os marcadores facilitam a visualização rápida de diferentes posições no rastreamento em relação a outros eventos e a sua anotação.
Você pode dar um nome descritivo para marcadores.
Selecione Exibir>Linha do Tempo para abrir a janela Linha do Tempo para que você possa acessar a linha do tempo dos Indicadores . Quando você passa o cursor sobre um favorito, o nome do favorito é exibido.
Clique com o botão direito do mouse no marcador para ir para a posição do marcador, renomear o marcador ou excluí-lo.
Observação
O recurso de marcador não está disponível na versão 1.2402.24001.0 do WinDbg.