!list
A extensão !list executa os comandos do depurador especificados repetidamente, uma vez para cada elemento em uma lista vinculada.
!list -t [Module!]Type.Field -x "Commands" [-a "Arguments"] [Options] StartAddress
!list " -t [Module!]Type.Field -x \"Commands\" [-a \"Arguments\"] [Options] StartAddress "
!list -h
Parâmetros
Módulo
Um parâmetro opcional que especifica o módulo que define essa estrutura. Se houver uma chance de que Type possa corresponder a um símbolo válido em um módulo diferente, você deve incluir Module para eliminar a ambiguidade.
Tipo
Define o nome de uma estrutura de dados.
Campo
Define o campo que contém o link da lista. Pode ser uma sequência de campos separados por pontos (em outras palavras, Type.Field.Subfield.Subsubfield e assim por diante).
-x "Comandos"
Define os comandos a serem executados. Pode ser qualquer combinação de comandos do depurador. Deve ser colocado entre aspas. Se vários comandos forem definidos, separe-os com ponto-e-vírgula, coloque toda a coleção de argumentos !list entre aspas e use um caractere de escape ( \ ) antes de cada aspa dentro dessas aspas externas. Se Commands for omitido, o padrão será dp (Memória de vídeo.
-a "Argumentos"
Define os argumentos para passar para o parâmetro Commands. Isso deve ser colocado entre aspas. Os Arguments podem ser qualquer cadeia de caracteres de argumento válida que normalmente teria permissão para seguir esse comando, exceto que Arguments não podem conter aspas. Se o prseudorregistro $extret estiver incluído em Commands, o parâmetro -a "Arguments" poderá ser omitido.
Opções Pode ser qualquer número destas opções:
-e
Ecoa o comando que está sendo executado para cada elemento.
-m Max
Define o número máximo de elementos para os quais executar o comando.
Endereço inicial
Define o endereço da primeira estrutura de dados. Esse é o endereço na parte superior da estrutura, não necessariamente o endereço do campo de link.
-h
Exibe um pequeno texto de Ajuda dessa extensão na janela de comando do depurador.
DLL
Ext.dll
Comentários
A extensão !list passará pela lista vinculada e emitirá o comando especificado uma vez para cada elemento da lista.
O prseudorregistro $extret é determinado como o valor do endereço de entrada de lista para cada elemento de lista. Para cada elemento, a sequência de comando Commands é executada. Essa cadeia de caracteres de comando pode fazer referência a esse prseudorregistro usando a sintaxe $extret. Se isso não aparecer na cadeia de caracteres de comando, o valor do endereço de entrada de lista será acrescentado ao final da cadeia de caracteres de comando antes da execução. Se precisar definir onde esse valor deve aparecer no seu comando, você deverá especificar esse prseudorregistro explicitamente.
Essa sequência de comandos será executada até que a lista termine em um ponteiro nulo ou termine fazendo um loop de volta para o primeiro elemento. Se a lista voltar para um elemento posterior, esse comando não será interrompido. No entanto, você pode parar esse comando a qualquer momento usando CTRL+C em KD e CDB, ou Depurar | Interromper ou CTRL+BREAK no WinDbg.
Cada vez que um comando for executado, o endereço da estrutura atual será usado como o endereço padrão se o comando que está sendo usado tiver parâmetros de endereço opcionais.
Veja a seguir dois exemplos de como usar esse comando no modo de usuário. O uso do modo kernel também é possível, mas segue uma sintaxe diferente.
Como um exemplo simples, imagine que você tem uma estrutura cujo nome de tipo é MYTYPE e que tem links dentro dos seus campos .links.Flink e .links.Blink. Você tem uma lista vinculada que começa com a estrutura em 0x6BC000. O seguinte comando de extensão percorrerá a lista e, para cada elemento, executará um comando dd L2. Como nenhum endereço está sendo especificado para o comando dd, ele usará o endereço do cabeçalho da lista como o endereço desejado. Isso faz com que os dois primeiros DWORDs em cada estrutura sejam exibidos.
0:000> !list -t MYTYPE.links.Flink -x "dd" -a "L2" 0x6bc00
Como um exemplo mais complexo, considere o caso do uso de $extret. Ele segue a lista de tipo _LIST_ENTRY em RtlCriticalSectionList. Para cada elemento, ele exibe os quatro primeiros DWORDS e, depois, a estrutura _RTL_CRITICAL_SECTION_DEBUG localizada em um deslocamento de oito bytes antes do elemento Flink da entrada da lista.
0:000> !list "-t ntdll!_LIST_ENTRY.Flink -e -x \"dd @$extret l4; dt ntdll!_RTL_CRITICAL_SECTION_DEBUG @$extret-0x8\" ntdll!RtlCriticalSectionList"
dd @$extret l4; dt ntdll!_RTL_CRITICAL_SECTION_DEBUG @$extret-0x8
7c97c0c8 7c97c428 7c97c868 01010000 00000080
+0x000 Type : 1
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : (null)
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x7c97c428 - 0x7c97c868 ]
+0x010 EntryCount : 0x1010000
+0x014 ContentionCount : 0x80
+0x018 Spare : [2] 0x7c97c100
dd @$extret l4; dt ntdll!_RTL_CRITICAL_SECTION_DEBUG @$extret-0x8
7c97c428 7c97c448 7c97c0c8 00000000 00000000
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : 0x7c97c0a0
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x7c97c448 - 0x7c97c0c8 ]
+0x010 EntryCount : 0
+0x014 ContentionCount : 0
+0x018 Spare : [2] 0