Surviving the Night

El blog de Pablo Doval sobre .NET, SQL, WinDbg...

January 2008 - Artículos

Malas Noticias: Nos ha dejado Ken Henderson

Hace unos minutos, mientras hacía mi recorrido bloguero habitual, me encontré con esta triste noticia en el blog de Kalen Delaney.

Ken Henderson, desarrollador del grupo de producto de SQL Server y uno de los mejores divulgadores de SQL Server (desde mi punto de vista), nos dejó el pasado 27 de Enero. Sirva este post para recordarle, para expresar mis mejores deseos para su familia, y para presentar su trabajo a quienes aun no lo conozcan. Como esta última parte es la más relevante para la comunidad, ahí os dejo la referencia de los que para mi son sus dos libros mas interesantes, y un par de artículos suyos geniales:

  • SQL Server 2005 Practical Troubleshooting:

Un libro genial sobre el proceso de resolución de problemas en SQL Server. En este enlace tenéis su entrada en Amazon.

  • The Guru's Guide to SQL Server Architecture and Internals

Este libro es una de mis recomendaciones sobre arquitectura del producto, complementando al Inside SQL Server 2000 de Kalen Delaney (o su versión de 2005, The Storage Engine). Sencillamente genial, imprescindible para conocer esos detalles del producto y la arquitectura que acaban marcando la diferencia, y sobre todo, capaz de hacernos entender por qué es importante conocer los internals.

Aquí tenéis su entrada en Amazon.

  • The Perils of Fiber Mode (Artículo de la MSDN)

En este artículo de la MSDN, Ken Henderson nos hablaba sobre el modo de 'lightweight threading', o 'fiber mode'.

  • Inside SQL Server 2000's Memory Management Facilities (Artículo de la MSDN)

Uno de mis temas de conversación favoritos al hablar sobre SQL Server es la gestión de memoria; no solo por lo bonito que puede llegar a ser el tema a nivel técnico, sino porque es uno de los pilares fundamentales sobre los que se sustenta el producto, y comprender como funciona la gestión de memoria nos ayuda en gran medida a tener nuestro sistema en un estado saludable y con un buen rendimiento. Un de los primeros artículos que leí sobre el tema fue este, y aún sigo recomendándolo como introducción a la gestión de memoria para máquinas de 32 bits.

Otra de las grandísimas contribuciones de Ken, junto con Bart Duncan, es la herramienta SQL Nexus, a la que espero dedicar un post en breves.

En fin, una gran perdida, justo un año después de la desaparición de Jim Gray... parece que Enero no es un buen mes para los Data Guys :(

Rock Tip:

Para acompañar este triste post hoy les pediré a los Suaves, los eternos rockeros ourensanos, que me dejen prestado su ya clásico 'Malas Noticias'.

Round And Round: Retraso para el SQL Server 2008 RTM

Acabo de leer la noticia en este post de The Data Platform Insider, y la verdad es que no me ha cogido por sorpresa: la versión final de SQL Server 2008 (Katmai para los amigos) se retrasa hasta el Q3 de 2008.

¿Y como afecta eso a los eventos de lanzamiento previstos para finales de septiembre? Pues realmente no les afecta en absoluto, ya que era sabido que se iban a realizar con una CTP. Las buenas noticias son que para este evento saldrá una nueva CTP que debería implementar toda la funcionalidad que se va a encontrar disponible en el producto final, y que en Q2 tendremos una RC a nuestra disposición que debería contener prácticamente los bits finales.

Personalmente el retraso del producto no me parece sorprendente, ni lo considero una mala señal; prefiero que el producto salga bien, y de paso, nos dan mas tiempo para ponernos las pilas con las CTP y RCs antes de plantearnos siquiera moverlo a producción. Sin embargo, me gustaría saber vuestra opinión :)

Rock Tip:

No se porque razón, si es que hay alguna, pero para describir esta noticia solo se me viene a la cabeza el temazo de RATT "Round And Round", de su disco Out of the Cellar, pero tampoco le daré vueltas, ya que nunca es mal momento para escuchar este trallazo de 1984 :)

El tema nunca pasará de moda, y ahí no acepto discusión. Pero el vídeo... el vídeo es sencillamente genial: una mansión de una familia rica, un grupo de melenudos que furtivamente se meten en su casa a tocar en el ático, una chica guapa y un mayordomo que acaba convertido en heavy... ¿alguien da mas? Y si, por si alguien se lo pregunta, ¡realmente me encantan! :)

Here Comes The Sun: Sun Compra a MySQL

Hoy traigo noticias frescas. Quizá no sean tan impactantes para el público no-geek como los últimos acontecimientos de la política nacional, o la expectación ante el derbi madrileño, o la aberrante propuesta a letra del himno nacional; sin embargo, estoy seguro de que vosotros si comprenderéis la importancia que tiene en nuestro terreno.

En fin, ahí va la noticia prometida:

(Redoble de tambores por favor... )

¡¡Sun Microsystems ha comprado a MySQL AB!!

¿Sorprendidos? Pues no deberíais, que para algo puse la noticia en el titulo del post :D

En fin, me parece que esta noticia va a ser seria, ya que Sun lleva tiempo queriendo meterse en el negocio de las bases de datos, y así, de paso, se hace con la M del stack LAMP. Por otra parte, MySQL realmente necesitaba el empujón que una multi-nacional como Sun puede aportarles, por lo que parece una situación en la que las dos empresas salen ganando. Del mismo modo, estoy seguro que los usuarios de MySQL también lo recibirán como una buena noticia.

¿Como nos afecta esta noticia a los geeks de Microsoft?

Bueno, esta claro que MySQL es un producto en competencia directa con SQL Server Express, y como buenos profesionales debemos conocer el producto que empleamos, así como las alternativas en el mercado. Y creedme que hasta yo, que no soy precisamente un fiel seguidor de MySQL, dedicaré mi tiempo a seguir los frutos de esta unión y evaluar los productos que saquen.

En fin, estoy ansioso de que saquen un producto nuevo... como siempre digo para mi todo son juguetes, ¡y estoy dispuesto a jugar con ellos mientras me entretengan! ;)

Rock Tip:

El rock tip de este post era evidente, 'Here Comes the Sun' de The Beatles. No obstante, como veréis si pincháis en el enlace, os sugiero la versión que Bon Jovi hizo en el concierto de homenaje a George Harrison en 2001. Una versión preciosa de una canción aun mas bonita si cabe. Se que no es un Rock tip propiamente dicho, pero no podía dejarla escapar ;) Si buscáis algo más rockero ¡no os perdáis el tema apócrifo de Europe del mismo nombre!

En fin, Sun... sun... sun... here it comes ;)

Posted: 18/1/2008 18:28 por Pablo Alvarez | con 3 comment(s)
Archivado en: ,
Rock and Roll All Nite: ¡Nuevo Foro de SQL Server!

A lo mejor alguno de vosotros ya se ha fijado: los reyes magos nos han traído un nuevo foro a geeks.ms, que estará dedicado a SQL Server. Espero que podamos animarlo a base de curiosidades, puzzles de SQL, encuestas y como no, resolución de problemas; eso si, ¡espero que esta última categoría sea la menos frecuente!

Por tanto este post es un llamamiento a toda la comunidad de eseculeros (con perdón :P): Si tenéis problemas con un SQL Server cabezón que no quiere arrancar, o con uno que va mas despacito que mi amigo el pezuñas después de pulsar el botón que no debía, o simplemente queréis comentar alguna curiosidad del producto, no dejéis de hacerlo en el nuevo foro. Si no tenéis ninguna duda, ¡pasaros también para ayudarnos a los que podamos tenerlas! :P

También me veo en la obligación moral de comentaros que seguramente no me pase por este nuevo foro durante unos días, ni termine el siguiente artículo sobre WinDbg; los reyes me han regalado un Guitar Hero para la Wii y hasta que no logre esto no dejare de practicar... por lo que estaré uno o dos días ocupadillo :)

Rock Tip:

Para la entrada de hoy no me he podido resistir a poner como Rock Tip el 'Rock and Roll All Nite', del album 'Dressed to Kill' de KISS. Primero, porque sale en el Guitar Hero. Segundo, porque ya era hora de poner un Rock Tip dedicado a los KISS, y por ultimo ¡porque es lo que tengo pensado hacer! ¡Rockanrolear toda la noche(*)! :D

(*) ¡Con el guitar Hero! ¡Malpensaos! :P

Teaser: Descubriendo WinDbg

Que triste será el día en que yo sea abuelo, y cuando mis nietos me pidan que les cuente mis locuras de juventud solo se me ocurran cosas como la noche en que algunos compañeros de Plain Concepts nos pusimos a crackear el buscaminas con el WinDdg a eso de las 2:00 am.

La verdad es que siempre he sido un poco raro para estas cosas: de pequeño no se me daba nada bien jugar a los juegos de plataformas, así que tiraba de SoftIce (el viejo, para DOS, de NuMega :) ) y me dejaba matar algunas vidas, miraba a ver que direcciones de memoria seguían un patrón de decrecimiento, y cuando localizaba la dirección de memoria que almacenaba el número de vidas, lo ponía a FF, y voilá, 256 vidas ;) ¡El proceso era más divertido muchas veces que el propio juego!

Supongo que debido a este oscuro pasado mío, mis ojos se abrieron como platos cuando descubrí la depuración postmortem de la mano,principalmente, de Nacho Alonso y David Salgado, y del resto de mis compañeros de Soporte en Microsoft, a los que les debo un buen cacho de lo que soy (¡¡un abrazote a todos!!). Desde ese momento me enganche al WinDbg, y hasta hoy me dura la tontería ;)

Espero poder dedicar algunas entradas de este blog a introducir el WinDbg, así como escenarios útiles (y no tan útiles! XD) de uso.

Que es el WinDbg

Microsoft pone a nuestra disposición (bajo licencia BTF, esto es, By The Face XD) las Debugging Tools for Windows, una suite de aplicaciones y documentación destinadas a la depuración en sistemas Windows. WinDbg es una de éstas herramientas: concretamente es un depurador que nos permite adjuntarnos a procesos de usuario y al kernel del sistema operativo (por tanto, soporta tanto user mode debugging como kernel mode debugging), que permite tanto la depuración en vivo (live debugging), que consiste en adjuntarse a un proceso que está en ejecución, como la depuración postmortem, mediante el análisis de volcados de memoria generados por la aplicación o el sistema operativo en momentos determinados. Y además de todo esto, ¡dispone de una interfaz gráfica! Bueno, o eso al menos dicen los de Redmond, porque muy gráfica la verdad es que no lo es :) Os adjunto un pantallazo de una sesión de depuración:

 WinDbg1

Como podéis ver, la ventana de comandos parece cualquier cosa menos gráfica :) Esto tiene una explicación: todos los depuradores de Microsoft tratan de mantener la compatibilidad a nivel de comandos. Si sabemos utilizar WinDbg, podremos saltar fácilmente a KD, CDB o NTSD, que son los depuradores de consola de Windows.

La diferencia mas notable entre el WinDbg y los otros tres depuradores comentados es la extensibilidad mediante módulos; algunos de las extensiones más conocidas son la Son of Strike (sos.dll), que nos permite depurar código administrado, y la SIEExtPub.dll, que entre otras cosas permite listar regiones criticas.

Un ejemplo: depurando el notepad.exe

Ok, ya sabemos lo que es el WinDbg, y sabemos donde encontrarlo, así que si os animáis, acompañadme en una demo muy corta para familiarizarnos con él. Simplemente vamos a adjuntar el depurador a un proceso existente, en este caso el notepad.exe.

Para empezar, nos descargamos las Debugging Tools for Windows y las instalamos en nuestra máquina. A continuación, arrancamos WinDbg.exe y, ta-dah!, ahí tenemos nuestro depurador gráfico :)

Ahora necesitaremos el proceso al que nos vamos a adjuntar (en inglés debugee), que será en este caso el notepad.exe. Vamos a abrir el notepad y simulamos que vamos a abrir un fichero; pulsamos Ctrl+O y nos aparecerá la ventana donde podemos seleccionar el archivo a abrir. Ok, con esto, sin cerrar esa ventana ni abrir ningún fichero, hemos terminado de preparar nuestro debuggee. Debería aparecer como la imagen siguiente:

winDbg2

Volvemos ahora al WinDbg, pulsamos F6 (que es el acceso rápido para adjuntarse a un proceso de la máquina) y nos aparecerá una ventana como la siguiente, donde podemos seleccionar el proceso al cual nos queremos adjuntar.

image

El checkbox que aparece en la parte inferior de la ventana con el nombre de Noninvasive es muy importante. No vamos a entrar en mucho detalle ya que es el primer artículo de la serie, pero os adelantaré que si ese checkbox no esta marcado, cuando cerremos la sesión de depuración el proceso depurado se cerrará también. Como veis, es un detalle muy importante, sobre todo si estamos trabajando en un servidor de producción: yo me se de alguno que se olvido de poner el modo no invasivo mientras depuraba un SQL Server en producción... titiriti, titiriti.... :D

El otro detalle a destacar es que si bien los nombres del proceso ayudan, en muchas ocasiones no es suficiente para identificar el proceso exacto al que queremos adjuntarnos. Por ejemplo, si quisiéremos depurar una instancia concreta en un servidor con múltiples instancias, necesitaríamos recurrir al identificador del proceso (PID), ya que el nombre sería el mismo para todas las instancias (sqlservr.exe).

De todos modos, nosotros lo tenemos bien fácil en este caso: seleccionamos el notepad.exe y le damos al Ok. A continuación os aparecerá una ventana en la que se muestra un chorrazo de texto, que aunque no vamos a describir en detalle, os adelanto que es la lista de todos los módulos (ejecutable, dlls, etc) que conforman el proceso notepad.exe.

A partir de aquí el proceso a depurar esta detenido, y nosotros podemos empezar a lanzar comandos al WinDbg para analizar o modificar el proceso. Por ejemplo, si lanzamos el comando lm (acnonimo de List Modules) nos listará todos los módulos en memoria de ese proceso. A continuación os pongo un extracto de ésta salida en mi máquina:

0:011> lm
start             end                 module name
00000000`777d0000 00000000`77901000   kernel32   (deferred)             
00000000`77910000 00000000`779da000   USER32     (deferred)             
00000000`779e0000 00000000`77b5a000   ntdll      (export symbols)       C:\Windows\system32\ntdll.dll
00000000`fffa0000 00000000`fffcf000   notepad    (deferred)             
00000001`80000000 00000001`80083000   sfShellTools64   (deferred)             
000007fe`f47d0000 000007fe`f4858000   tiptsf     (deferred)             
000007fe`f5c10000 000007fe`f62d2000   ieframe    (deferred)             
000007fe`f7080000 000007fe`f7178000   actxprxy   (deferred)             
000007fe`f7390000 000007fe`f73eb000   ntshrui    (deferred)             
000007fe`f73f0000 000007fe`f7442000   msshsq     (deferred)             
000007fe`f7530000 000007fe`f75d7000   cscui      (deferred)             
...          

Como se puede ver, tenemos un modulo que se llama notepad. Podemos tratar de visualizar todas las funciones que expone mediante el comando x. Este nos muestra una lista de todos los indentificadores (nombres de funciones, de variables...)de un modulo, o los que cumplan cierto criterio mediante una expresión regular. En el siguiente ejemplo vamos a pedir que nos muestre todos los identificadores del modulo notepad:

0:011> x notepad!*
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\notepad.exe

Uuups, algo no está bien. Dice que faltan unos símbolos, y no nos muestra nada... bueno, vamos a ignorar de momento este mensaje. Fijaros simplemente en que la expresion que le pasamos fue <NombreModulo>!<expresionDeBusqueda>.

Vamos a intentar mostrar otra cosa interesante: los volcados de pila de todos los hilos del proceso. Para ello, nada mas simple que el terriblemente intuitivo comando ~*k. En mi máquina me ha devuelto 12 hilos, pero aqui voy a limitar la salida a un solo hilo:

0:011> ~*k

   0  Id: 1798.1548 Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
Child-SP          RetAddr           Call Site
00000000`000df348 00000000`7780ed73 ntdll!NtWaitForMultipleObjects+0xa
00000000`000df350 00000000`7792e96d kernel32!WaitForMultipleObjectsEx+0x113
00000000`000df460 000007fe`fccb1ab6 USER32!MsgWaitForMultipleObjectsEx+0x13d
00000000`000df500 000007fe`fccb371f DUser+0x1ab6
00000000`000df550 000007fe`fccb3696 DUser!DeleteHandle+0x7df
00000000`000df590 00000000`7791bd1a DUser!DeleteHandle+0x756
00000000`000df5c0 00000000`77a32016 USER32!CopyIcon+0x8a
00000000`000df610 00000000`7792df2a ntdll!KiUserCallbackDispatcher+0x1f
00000000`000df678 00000000`779173e9 USER32!WaitMessage+0xa
00000000`000df680 00000000`7791760a USER32!LockWindowUpdate+0x249
00000000`000df700 00000000`779174c6 USER32!DialogBoxIndirectParamAorW+0x19a
00000000`000df760 00000000`77917918 USER32!DialogBoxIndirectParamAorW+0x56
00000000`000df7a0 000007fe`fe473d2e USER32!DialogBoxIndirectParamW+0x18
00000000`000df7e0 00000000`fffa5146 COMDLG32!GetFileTitleW+0x121e
00000000`000df850 00000000`fffa547e notepad+0x5146
00000000`000df8c0 00000000`fffa5b98 notepad+0x547e
00000000`000df920 00000000`fffa6d33 notepad+0x5b98
00000000`000dfa50 00000000`7792e25a notepad+0x6d33
00000000`000dfaa0 00000000`7792cbaf USER32!GetWindowLongPtrW+0x13a
00000000`000dfb60 00000000`7792cdcd USER32!ReleaseDC+0x9f

   1  Id: 1798.310 Suspend: 1 Teb: 000007ff`fffda000 Unfrozen
Child-SP          RetAddr           Call Site
00000000`0304f528 00000000`7780ed73 ntdll!NtWaitForMultipleObjects+0xa
00000000`0304f530 00000000`7792e96d kernel32!WaitForMultipleObjectsEx+0x113
00000000`0304f640 000007fe`fccb1ab6 USER32!MsgWaitForMultipleObjectsEx+0x13d
00000000`0304f6e0 000007fe`fccb1aef DUser+0x1ab6
00000000`0304f730 000007fe`fccbe4ad DUser+0x1aef
00000000`0304f7a0 000007fe`fccbe3cc DUser!GetMessageExA+0x6d
00000000`0304f7f0 000007fe`fea994e7 DUser!RemoveGadgetProperty+0x59c
00000000`0304f880 000007fe`fea9967d msvcrt!_crtCompareStringW+0xf7
00000000`0304f8b0 00000000`7780cdcd msvcrt!beginthreadex+0x13d
00000000`0304f8e0 00000000`77a2c6e1 kernel32!BaseThreadInitThunk+0xd
00000000`0304f910 00000000`00000000 ntdll!RtlUserThreadStart+0x21

Si nos fijamos, podemos ver que algunos módulos, como kernel32, muestran los nombres de los métodos en cada frame de la pila, mientras que otros, como los de notepad, solamente nos muestran el nombre del módulo y un número hexadecimal al lado. Nuevamente, esto se debe a que no tenemos disponibles símbolos para el modulo notepad.exe (y muchos otros)....

Símbolos: Qué son, para qué nos sirven y dónde los conseguimos

¿Alguna vez os fijasteis en los ficheros de extensión .pdb que acompañan a vuestros binarios en la caperta \bin\debug? Pues si no los conocíais de antes, os los presento: son los símbolos de vuestro código. Su extensión es un acrónimo de Program Data Base, y su objetivo es servir de traducción entre direcciones de memoria u offsets dentro de un módulo y el nombre que se le ha dado a ese elemento durante el desarrollo, es decir, su identificador.

¿Y para que nos sirven? Precisamente para evitar lo que nos sucede en el ejemplo del notepad de arriba, en el cual no podemos ver casi ninguna información del módulo. A modo de ejemplo, imaginemos que tenemos libreria llamada matematicas.dll y un método dentro de ella llamado Sumar. Si tuviera los símbolos de ésta librería, desde WinDbg podria ver algo como matematicas!Sumar como nombre del método, pero si no tuvieramos los símbolos seguramente veríamos algo parecido a matematicas+0x1ab6, lo cual no nos da ninguna pista de lo que realiza ese método.

Para obtener los símbolos evidentemente hay que recurrir al desarrollador del producto. Si es un producto nuestro, tenemos que asegurarnos de tener los .pdb tanto para las versiones de debug como release (por defecto en Visual Studio, al compilar en modo release, no se generan los símbolos). Si se trata de un producto de terceros dependemos de que la empresa desarrolladora los distribuya. En el caso de Microsoft estamos parcialmente de enhorabuena, ya que gran cantidad de sus productos distribuyen los símbolos; eso si, una versión limitada de ellos, los llamados símbolos públicos.

WinDbg incorpora una gestión de símbolos muy avanzada, de modo que podemos montarnos nuestro propio servidor de símbolos en nuestro disco duro o en un directorio compartido de la red, lo cual es buena idea a medida que la colección va creciendo. Ya veréis como al final acabáis coleccionando símbolos como si fueran cromos :D

En mi caso, tengo una carpeta local con los símbolos (C:\Symbols), y en ella se descargan todos los símbolos que voy obteniendo. El propio WinDbg se encarga de ordenarla en directorios para que no haya problemas de versiones. Sin embargo, con la carpeta local no es suficiente, hay que especificar también servidores desde donde nos podamos descargar los símbolos que no tenemos. En este caso, solo os puedo dar uno, el servidor de símbolos públicos de Microsoft, que se encuentra en http://msdl.microsoft.com/download/symbols. Para especificar la ruta de símbolos podemos establecer la variable de entorno NT_SYMBOL_PATH o modificarla desde la interfaz de usuario del WinDbg (Ctrl+S o menú File -> File Symbol Path...). Para que no digáis que os hago pensar ni un poquitín, os dejo la cadena de símbolos que estoy utilizando para esta demo:

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

Una vez establecido nuestro servidor de símbolos, volvamos a la demo...

... y de vuelta a WinDbg

Con nuestros símbolos en orden, vamos a forzar a WinDbg a que nos vuelva a cargar los módulos y busque por los símbolos apropiados. Para ello emplearemos el comando .reload, que carga los símbolos de nuevo, y le pasamos los parámetros /v (verbose, es decir, nos imprime información detallada de los símbolos durante el proceso de carga) y /f (fuerza la carga de los símbolos. Si no se especifica este parámetro, los símbolos se cargan de modo perezoso, solo cuando son necesitados). A continuación pongo un fragmento de la salida en mi máquina:

0:011> .reload /v /f
Reloading current modules
AddImage: C:\Windows\system32\USER32.dll
 DllBase  = 00000000`77950000
 Size     = 000ca000
 Checksum = 000ce438
 TimeDateStamp = 45d3ee19
AddImage: C:\Windows\system32\kernel32.dll
 DllBase  = 00000000`77a20000
 Size     = 00131000
 Checksum = 0013758a
 TimeDateStamp = 4549d328
AddImage: C:\Windows\system32\ntdll.dll
 DllBase  = 00000000`77b60000
 Size     = 0017a000
 Checksum = 0017b5ee
 TimeDateStamp = 4549d372
AddImage: C:\Windows\system32\notepad.exe
 DllBase  = 00000000`fffe0000
 Size     = 0002f000
 Checksum = 0003024b
 TimeDateStamp = 4549bb19
...

Podemos ver como se están cargando los módulos, sus direcciones base, tamaño de los módulos, etc. Si queremos obtener un listado de todos los módulos y su estado, podemos repetir el comando lm que ya lanzamos antes. Esta vez la salida será similar a esta:

0:011> lm
start             end                 module name
00000000`77950000 00000000`77a1a000   USER32     (pdb symbols) (...)
00000000`77a20000 00000000`77b51000   kernel32   (pdb symbols) (...)
00000000`77b60000 00000000`77cda000   ntdll      (pdb symbols) (...)
00000000`fffe0000 00000001`0000f000   notepad    (pdb symbols) (...)
...

Podemos ver que los módulos ya están cargados (en lugar de deferred, nos aparece la etiqueta pdb symbols, o export symbols, etc.). Vamos a tratar de realizar las dos pruebas de antes, esto es, consultar todos los identificadores expuestos por el modulo notepad, y listar los call stack de algunos hilos para hacernos a la idea de lo que hacen.

En el primer caso, volvemos a lanzar el comando x para consultar información expuesta por el modulo (podemos pensar que x viene de eXplore... estaremos equivocados, pero funciona como regla mnemotécnica :P). En mi máquina tengo la siguiente salida:

0:011> x notepad!*
(...)
00000000`ffff1600 notepad!PrintTime = <no type information>
(...)
00000000`fffe7564 notepad!AlertBox = <no type information>
00000000`ffff0630 notepad!szLoadDrvFail = <no type information>
00000000`fffe25f0 notepad!IID_IQuickFilterPriv = <no type information>
00000000`fffe10b8 notepad!_imp_GetTextExtentPoint32W = <no type information>
(...)
00000000`ffff0578 notepad!szUntitled = <no type information>
(...)

Si recordáis, antes de tener los símbolos cargados no obteníamos ninguna salida al ejecutar este comando, mientras que ahora tenemos una lista enorme con todos los identificadores del módulo. Imaginaros que nos interesa buscar todos los métodos relacionados con la acción de guardar el fichero; podemos intentar lanzar una consulta como la siguiente:

0:011> x notepad!*Save*
00000000`fffe635c notepad!CheckSaveTaskDlgBox = <no type information>
00000000`fffe5068 notepad!ShowOpenSaveDialog = <no type information>
00000000`fffe8268 notepad!SaveGlobals = <no type information>
00000000`fffe54c4 notepad!InvokeLegacySaveDialog = <no type information>
00000000`ffff1384 notepad!fInSaveAsDlg = <no type information>
00000000`fffe32f0 notepad!IID_IViewSaveRestriction = <no type information>
00000000`fffe24d0 notepad!IID_IFileSaveDialogOld = <no type information>
00000000`ffff20c0 notepad!szSaveFilterSpec = <no type information>
00000000`fffe4548 notepad!s_SaveAsHelpIDs = <no type information>
00000000`fffe17a0 notepad!IID_IFileSaveDialog = <no type information>
00000000`fffe55f4 notepad!InvokeSaveDialog = <no type information>
00000000`fffe24a0 notepad!IID_IFileSaveDialogPrivate = <no type information>
00000000`ffff20b0 notepad!g_ftSaveAs = <no type information>
00000000`fffe64c0 notepad!CheckSave = <no type information>
00000000`ffff0620 notepad!szSaveCaption = <no type information>
00000000`fffe7a90 notepad!NpSaveDialogHookProc = <no type information>
00000000`fffe17e0 notepad!CLSID_FileSaveDialog = <no type information>
00000000`fffe33c0 notepad!CLSID_ScreenSaverPage = <no type information>
00000000`fffe9e00 notepad!SaveFile = <no type information>
00000000`fffe1050 notepad!_imp_GetSaveFileNameW = <no type information>

Ahora vamos a comprobar como se ven la pila de llamadas de un hilo del proceso:

0:011> ~*k

   0  Id: ff4.6cc Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
Child-SP          RetAddr           Call Site
00000000`0010f288 00000000`77a5ed73 ntdll!NtWaitForMultipleObjects+0xa
00000000`0010f290 00000000`7796e96d kernel32!WaitForMultipleObjectsEx+0x10b
00000000`0010f3a0 000007fe`fcf31ab6 USER32!RealMsgWaitForMultipleObjectsEx+0x129
00000000`0010f440 000007fe`fcf3371f DUser!CoreSC::Wait+0x62
00000000`0010f490 000007fe`fcf33696 DUser!CoreSC::WaitMessage+0x6f
00000000`0010f4d0 00000000`7795bd1a DUser!MphWaitMessageEx+0x36
00000000`0010f500 00000000`77bb2016 USER32!_ClientWaitMessageExMPH+0x1a
00000000`0010f550 00000000`7796df2a ntdll!KiUserCallbackDispatcherContinue
00000000`0010f5b8 00000000`779573e9 USER32!ZwUserWaitMessage+0xa
00000000`0010f5c0 00000000`7795760a USER32!DialogBox2+0x261
00000000`0010f640 00000000`779574c6 USER32!InternalDialogBox+0x134
00000000`0010f6a0 00000000`77957918 USER32!DialogBoxIndirectParamAorW+0x58
00000000`0010f6e0 000007fe`fe623d2e USER32!DialogBoxIndirectParamW+0x18
00000000`0010f720 00000000`fffe5146 COMDLG32!CFileOpenSave::Show+0x143
00000000`0010f790 00000000`fffe547e notepad!ShowOpenSaveDialog+0xde
00000000`0010f800 00000000`fffe5b98 notepad!InvokeOpenDialog+0x136
00000000`0010f860 00000000`fffe6d33 notepad!NPCommand+0x380
00000000`0010f990 00000000`7796e25a notepad!NPWndProc+0x55b
00000000`0010f9e0 00000000`7796cbaf USER32!UserCallWinProcCheckWow+0x1ad
00000000`0010faa0 00000000`7796cdcd USER32!DispatchClientMessage+0xc3
(...)

Ahora, a diferencia de cuando los símbolos no estaban cargados, podemos ver mucha mas información en la pila de llamadas, como los nombres de los métodos del módulo de notepad que antes no veíamos. Podemos ver que este hilo en cuestión invoca la ventana para abrir o guardar un fichero, mediante las llamadas a InvokeOpenDialog en notepad, y posteriormente la llamada al método Show de un CFileOpenSave en el modulo COMDLG32, que a su vez llama a... no sigo, que creo que se entiende suficientemente bien y ya me voy cansando :)

En fin, con esto hemos dado un repaso general a WinDbg, aunque no hemos hecho nada mas que rascar la superficie. No os preocupéis por los comandos, por las pilas de llamadas ni por nada mas, lo iremos viendo con calma en los siguientes posts (¡si es que os interesan!). Me conformo por ahora con que hayáis podido abrir el WinDbg, adjuntaros a un proceso y comprendido la importancia de los símbolos.

Conclusiones:

En este post hemos comentado las herramientas principales que vamos a emplear, hemos hablado de los símbolos y hemos realizado nuestra primera sesión de depuración con WinDbg: no esta mal. Pero venga... se que lo estáis pensando. A no ser que seáis muy apasionados del bajo nivel, o que tengáis mucho tiempo libre, os estaréis preguntando ¿Para que quiero yo saber todo esto? Pues allá van algunas razones que considero que pueden justificar el pelearse con el WinDbg:

  • Si nuestro sistema nos muestra una pantalla azul de la muerte, podemos tratar de analizar el minidump (volcado de memoria de pequeñas dimensiones) que nos genera con WinDbg para determinar que módulo fue el causante del error. Así podemos determinar si el problema se originó en el controlador de disco, de vídeo, en el propio kernel, etc.
  • Ciertas aplicaciones, como SQL Server, generan volcados de memoria cuando suceden eventos inesperados, errores, etc. Mediante WinDbg podemos intentar acercarnos al origen del problema, aunque sin los símbolos apropiados (y estos símbolos son, generalmente, privados) será muy dificil profundizar en la investigación. No obstante, al menos tendremos cierto conocimiento de como capturar volcados, que nos facilitará la tarea de colaborar con los servicios de soporte de Microsoft.
  • Jugando con WinDbg aumentamos notablemente nuestro conocimiento de la plataforma sobre la que trabajamos, lo cual siempre es positivo. De echo, esta es la razón que personalmente mas me motiva y por la que sigo jugando siempre que puedo con depuradores :)
  • Tu última sesión de depuración siempre es un buen tema de conversación para esos ratos de cervezas con los colegas... XD
Rock Tip:

Como el artículo de hoy es tan solo una pequeña introducción a lo que espero que sea una serie de artículos sobre WinDbg y depuración en general, el tema 'Teaser', de Yngwie J. Malmsteen, me viene que ni pintado.

Para los que no le conozcáis, el señor Malmsteen es uno de los guitar heroes más conocidos, un virtuoso de corte neoclásico con igual número de seguidores que de detractores (los detractores son por pura envidia cochina xD). Si bien no es mi guitarrista favorito, he de admitir que sus discos mas ochenteros me llegan al alma. Dentro de este estilo os recomendaría especialmente el Eclipse (NOTA: Este link NO lleva a ningún IDE extraño... ¡¡siempre seré fiel a mi Visual Studio!!).

Posted: 3/1/2008 13:28 por Pablo Alvarez | con 19 comment(s) |
Archivado en: ,