Archive for September, 2010

Step into Kernel (VMware 7+WinDbg)

4 de September de 2010

A primeira impressão, que alguns leitores mais antigos podem estar tendo agora, é a de que eu estou ficando realmente sem tempo de escrever novos posts, e por isso, esse novo post seria apenas uma repetição do post Step into Kernel (WMware+WinDbg). Na verdade estou tão surpreso quanto alguns de vocês. Neste post vou falar sobre um pequeno detalhe que vai fazer diferença na hora de fazer debug de Kernel utilizando uma máquina virtual criada com a nova versão da VMware.

O Sintoma

Neste último final de semana, apesar do feriado, do sol e da imensa vontade de pôr o pé na estrada,  tive que ficar em casa resolvendo algumas tretas pessoais. Uma delas envolvia fazer debug de Kernel numa máquina virtual. Nada de incomum nisso até agora. Afinal de contas, fazer debug de Kernel em máquinas virtuais é arroz com feijão para quem trabalha desenvolvendo drivers.

Criei uma VM nova e instalei o Windows nela, realizei as configurações TARGET e HOST exatamente como descrevo naquele outro post, mas para minha surpresa, por algum motivo o WinDbg não conseguia se conectar ao sistema TARGET, permanecendo sempre com a mesma mensagem “Waiting to reconnect…”. Mesmo usando o Ctrl+Alt+D no WinDbg para ver informações internas do depurador, tudo o que eu tinha na saída do WinDbg era a mensagem exibida abaixo.

 
Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
 
Opened \\.\pipe\com_1
Waiting to reconnect...
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
SYNCTARGET: Timeout.
>>>> ReadAll(0x800703E3,1,0) fails.
Throttle 0x10 write to 0x1
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.
>>>> ReadAll(0x800703E3,1,0) fails.

Depois de verificar todos os passos minuciosamente várias vezes, eu não conseguia entender o que estava acontecendo.

A Causa

Ao criar uma nova porta serial na máquina virtual, a qual seria redirecionada para um named pipe na máquina real, reparei que seu nome estava fora do comum. Apesar de esta ser supostamente a única porta serial do sistema, a interface de edição de configurações da VMware mostrava seu nome como “Serial Port 2” como mostra a figura abaixo.

Desconfiei disso e tentei recriar a porta serial achando que seria um bug na inteface da VMware, mas o mesmo nome apareceu. Então nada melhor que abrir o arquivo de configuração da VM no bom e velho Notepad. Foi então que descobri que apesar de não haver uma porta serial além da que eu estava criando na interface de edição da VMware, no arquivo de configuração de fato haviam duas portas seriais como mostro abaixo.

.encoding = "windows-1252"
config.version = "8"
virtualHW.version = "7"
scsi0.present = "TRUE"
scsi0.virtualDev = "lsisas1068"
memsize = "1024"
mem.hotadd = "TRUE"
scsi0:0.present = "TRUE"
scsi0:0.fileName = "Windows 7 x64.vmdk"
ide1:0.present = "TRUE"
ide1:0.autodetect = "TRUE"
ide1:0.deviceType = "cdrom-raw"
floppy0.startConnected = "FALSE"
floppy0.fileName = ""
floppy0.autodetect = "TRUE"
ethernet0.present = "TRUE"
ethernet0.connectionType = "nat"
ethernet0.virtualDev = "e1000"
ethernet0.wakeOnPcktRcv = "FALSE"
ethernet0.addressType = "generated"
usb.present = "TRUE"
ehci.present = "TRUE"
sound.present = "TRUE"
sound.fileName = "-1"
sound.autodetect = "TRUE"
mks.enable3d = "TRUE"
serial0.present = "TRUE"
serial0.fileType = "thinprint"
pciBridge0.present = "TRUE"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge4.functions = "8"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
vmci0.present = "TRUE"
roamingVM.exitBehavior = "go"
displayName = "Windows 7 x64"
guestOS = "windows7-64"
nvram = "Windows 7 x64.nvram"
virtualHW.productCompatibility = "hosted"
printers.enabled = "TRUE"
extendedConfigFile = "Windows 7 x64.vmxf"
ide1:0.startConnected = "TRUE"
ethernet0.generatedAddress = "00:0c:29:91:aa:62"
tools.syncTime = "FALSE"
uuid.location = "56 4d a8 8a e8 f9 f0 a8-62 de e8 25 40 91 aa 62"
uuid.bios = "56 4d a8 8a e8 f9 f0 a8-62 de e8 25 40 91 aa 62"
cleanShutdown = "FALSE"
replay.supported = "FALSE"
replay.filename = ""
scsi0:0.redo = ""
pciBridge0.pciSlotNumber = "17"
pciBridge4.pciSlotNumber = "21"
pciBridge5.pciSlotNumber = "22"
pciBridge6.pciSlotNumber = "23"
pciBridge7.pciSlotNumber = "24"
scsi0.pciSlotNumber = "160"
usb.pciSlotNumber = "32"
ethernet0.pciSlotNumber = "33"
sound.pciSlotNumber = "34"
ehci.pciSlotNumber = "35"
vmci0.pciSlotNumber = "36"
scsi0.sasWWID = "50 05 05 6a e8 f9 f0 a0"
vmotion.checkpointFBSize = "134217728"
usb:0.present = "TRUE"
usb:1.present = "TRUE"
ethernet0.generatedAddressOffset = "0"
vmci0.id = "1083288162"
usb:1.deviceType = "hub"
usb:0.deviceType = "mouse"
ide1:0.fileName = "auto detect"
unity.wasCapable = "FALSE"
serial1.yieldOnMsrRead = "TRUE"
serial1.fileName = "\\.\pipe\com_1"
serial1.pipe.endPoint = "server"
 

A propriedade “filetype” com o valor “thiprint” na porta serial zero me fez prestar atenção neste novo hardware que fazia parte das configurações da minha máquina virtual e eu nem tinha reparado.

O fato de essa impressora utilizar a porta COM1 da máquina virtual como interface de hardware, fazia com que qualquer nova porta serial utilizasse a COM2, que seria a próxima porta vaga. Agora ficou simples de resolver.

A Solução

Existem duas maneiras de resolver esse pequeno contratempo. A primeira, que minha opinião é mais simples e tosco, é simplesmente remover a impressora antes de adicionar a porta serial que será utilizada como interface de debug. Isso fará com que a primeira porta serial seja realmente utilizada como porta serial. Caso você necessite utilizar a impressora, então adicione e impressora após a adição da porta serial. Isso fará com que a impressora utilize a primeira porta serial disponível, que no caso é a COM2. A janela de configuração de hardware da VMware deve ficar como exibida na figura abaixo.

Reparem que o nome da porta serial não leva mais o número 2 enquanto que na configuração da impressora diz que a porta utilizada é a serial 2.

A segunda solução, como uma alternativa à primeira, é simplesmente configurar o lado TARGET para que ele utilize a porta serial 2. No exemplo da figura abaixo, eu mudo a configuração de um Windows 7 utilizando a ferramenta BcdEdit. Já comentei dessa ferramenta neste post, que fala sobre como fazer debug de Kernel através de portas USB utilizando o Windows Vista.

Depois de tudo resolvido, o depurador agora conecta ao sistema TARGET e agora vem a parte mais fácil; depurar o problema. 😉

Até mais!