Guia de rastreamento dinâmico Solaris

Provedor pid

O provedor pid permite que você rastreie qualquer instrução em um processo. Ao contrário da maioria dos outros provedores, os testes pid são criados por demanda com base nas descrições de teste encontradas em seus programas em D. Como resultado, nenhum teste pid estará listado na saída do dtrace -l até que você os tenha ativado.

Rastreio de limite de função do usuário

O modo mais simples de operação do provedor pid é como um espaço do usuário análogo ao provedor fbt. O programa de exemplo seguinte rastreia todas as entradas e os retornos da função feitos a partir de uma única função. A variável de macro $1 (o primeiro operando na linha de comando) é o ID do processo a ser rastreado. A variável de macro $2 (o segundo operando na linha de comando) é o nome da função a partir da qual serão rastreadas todas as chamadas de função.


Exemplo 33–1 userfunc.d: rastrear retorno e entrada de função do usuário

pid$1::$2:entry
{
	self->trace = 1;
}

pid$1::$2:return
/self->trace/
{
	self->trace = 0;
}

pid$1:::entry,
pid$1:::return
/self->trace/
{
}

Digite o script de exemplo acima e salve-o em um arquivo chamado userfunc.d e, em seguida, execute o comando chmod para torná-lo executável. Este script produz uma saída semelhante ao exemplo seguinte:


# ./userfunc.d 15032 execute
dtrace: script './userfunc.d' matched 11594 probes
  0  -> execute                               
  0    -> execute                             
  0      -> Dfix                              
  0      <- Dfix                              
  0      -> s_strsave                         
  0        -> malloc                          
  0        <- malloc                          
  0      <- s_strsave                         
  0      -> set                               
  0        -> malloc                          
  0        <- malloc                          
  0      <- set                               
  0      -> set1                              
  0        -> tglob                           
  0        <- tglob                           
  0      <- set1                              
  0      -> setq                              
  0        -> s_strcmp                        
  0        <- s_strcmp                        
...

O provedor pid só pode ser usado em processos que já estão sendo executados. Você pode usar a variável de macro $target (consulte o Capítulo 15Script) e as opções -c and -p do dtrace para criar e usar processos de interesse e instrumentá-los usando o DTrace. Por exemplo, o script de D seguinte pode ser usado para determinar a distribuição de chamadas de função feitas para libc por um processo de assunto específico:

pid$target:libc.so::entry
{
	@[probefunc] = count();
}

Para determinar a distribuição de tais chamadas feitas pelo comando date(1), salve o script em um arquivo chamado libc.d e execute o comando seguinte:


# dtrace -s libc.d -c date
dtrace: script 'libc.d' matched 2476 probes
Fri Jul 30 14:08:54 PDT 2004
dtrace: pid 109196 has exited

  pthread_rwlock_unlock                                             1
  _fflush_u                                                         1
  rwlock_lock                                                       1
  rw_write_held                                                     1
  strftime                                                          1
  _close                                                            1
  _read                                                             1
  __open                                                            1
  _open                                                             1
  strstr                                                            1
  load_zoneinfo                                                     1

...
  _ti_bind_guard                                                   47
  _ti_bind_clear                                                   94

Rastreando instruções arbitrárias

Você pode usar o provedor pid para rastrear qualquer instrução em qualquer função do usuário. Por demanda, o provedor pid criará um teste para cada instrução em uma função. O nome de cada teste é o deslocamento de sua instrução correspondente na função expressa como um inteiro hexadecimal. Por exemplo, para ativar um teste associado à instrução no deslocamento 0x1c na função foo do módulo bar.so no processo com PID 123, use o seguinte comando:


# dtrace -n pid123:bar.so:foo:1c

Para ativar todos os testes na função foo, incluindo o teste de cada instrução, use o comando:


# dtrace -n pid123:bar.so:foo:

Esse comando demonstra uma técnica extremamente poderosa para depurar e analisar os aplicativos do usuário. Erros infreqüentes podem ser difíceis de depurar por serem difíceis de reproduzir. Freqüentemente, você pode identificar um problema após a ocorrência de uma falha muito tardiamente para reconstruir o caminho do código. O exemplo seguinte demonstra como combinar o provedor pid com rastreio especulativo (consulte o Capítulo 13Rastreio especulativo) para resolver este problema rastreando cada instrução em uma função.


Exemplo 33–2 errorpath.d: rastrear o caminho de erro da chamada da função do usuário

pid$1::$2:entry
{
	self->spec = speculation();
	speculate(self->spec);
	printf("%x %x %x %x %x", arg0, arg1, arg2, arg3, arg4);
}

pid$1::$2:
/self->spec/
{
	speculate(self->spec);
}

pid$1::$2:return
/self->spec && arg1 == 0/
{
	discard(self->spec);
	self->spec = 0;
}

pid$1::$2:return
/self->spec && arg1 != 0/
{
	commit(self->spec);
	self->spec = 0;
}

Executar errorpath.d resulta em uma saída semelhante ao exemplo seguinte:


# ./errorpath.d 100461 _chdir
dtrace: script './errorpath.d' matched 19 probes
CPU     ID                    FUNCTION:NAME
  0  25253                     _chdir:entry 81e08 6d140 ffbfcb20 656c73 0
  0  25253                     _chdir:entry
  0  25269                         _chdir:0
  0  25270                         _chdir:4
  0  25271                         _chdir:8
  0  25272                         _chdir:c
  0  25273                        _chdir:10
  0  25274                        _chdir:14
  0  25275                        _chdir:18
  0  25276                        _chdir:1c
  0  25277                        _chdir:20
  0  25278                        _chdir:24
  0  25279                        _chdir:28
  0  25280                        _chdir:2c
  0  25268                    _chdir:return