[Windbg Script] Serviced Components

A few days ago a friend of mine, Fabrício Catae, a SQL Server Ranger here at Microsoft, gave me an idea: to create a script that shows if Serviced Components are or are not disposed.

I thought it was a great idea, so I decided to create a script for it. During the development I added more features related to Serviced Components.

Basically this script gives you the following information related to Serviced Components:

- Object Pooled (Not Pooled)

- Jit Activated (Not Activated)

- Use Interface IDispatch (Not using IDispatch)

- Server Activated (Not Activated)

- Active (Not Active)

- Finalized (Not Finalized)

- Returned By Finalizer (Not Returned By Finalizer)

- Disposed (Not Disposed)

Note: I didn’t have an opportunity to stress this script in the trenches. It might have hidden bugs. If you find something, please, let me know and I’ll fix it.

Note 2: The next article will be about books to help you improve or acquire debugging skills.

Screenshots:

 

Source code for SERVICED_COMPONENTS.TXT:

$$

$$ =============================================================================

$$ Get details from Serviced Components, like:

$$ - Object Pooled

$$ - Jit Activated

$$ - Use Interface IDispatch

$$ - Server Activated

$$ - Active

$$ - Finalized

$$ - Returned By Finalizer

$$ - Disposed

$$

$$ Compatibility: Win32.

$$

$$ Usage: $$>< to run the program.

$$

$$ Attention! If you get a syntax error if calling it a 2nd time, run ad /q * then

$$ call the script again.

$$

$$ Requirements: Public symbols.

$$

$$ If necessary change the filename below to include your path and filename.

$$ By default it uses the WinDbg path and the default file name is SERVICED_COMPONENTS.TXT

$$

$$ Roberto Alexis Farah

$$ Blog: https://blogs.msdn.com/debuggingtoolbox/

$$

$$ All my scripts are provided "AS IS" with no warranties, and confer no rights.

$$ =============================================================================

$$

r @$t0 = 0

ad /q *

.block

{

    as ScriptName MYSCRIPTS\\SERVICED_COMPONENTS.TXT

}

.block

{

     .block

     {

         as ObjectPooled .block

                         {

                             .block

                             {

                                 j (0 = @$t0) '.printf /D "<b>\nObjects Pooled\n\n</b>"';'.printf /D "<b>\nObjects NOT Pooled\n\n</b>"'

                             }

                             .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                             {

                                 r @$t1 = poi(${obj}+0xC)

                           .if(0 != @$t1)

                                 {

                                     r @$t2 = poi(${obj}+0x34)

                                     .if(0 = @$t0)

                                     {

                                         .if(@$t2 & 0x1)

                                         {

                                             .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                             !do @$t1

                                             .printf "\n###############################################################################\n"

                                         }

                                     }

                              .else

                                     {

                                         .if(0 = (@$t2 & 0x1))

                                         {

                                             .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                             !do @$t1

                                             .printf "\n###############################################################################\n"

                                         }

              }

                                 }

                             }

                         }

 

     }

     .block

     {

         as IsJitActivated .block

                           {

                             .block

                             {

                                   j (0 = @$t0) '.printf /D "<b>\nJIT Activated\n\n</b>"';'.printf /D "<b>\nJIT NOT Activated\n\n</b>"'

                               }

                               .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                               {

                                   r @$t1 = poi(${obj}+0xC)

 

                                   .if(0 != @$t1)

              {

                                       r @$t2 = poi(${obj}+0x35)

                                       .if(0 = @$t0)

                                       {

                                           .if(@$t2 & 0x1)

              {

                                               .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                               !do @$t1

                                               .printf "\n###############################################################################\n"

                                           }

                                       }

                                       .else

                                       {

       .if(0 = (@$t2 & 0x1))

                                           {

                                               .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                               !do @$t1

                                               .printf "\n###############################################################################\n"

                                           }

                                       }

                    }

 

                               }

                           }

 

     }

     .block

     {

         as UseInterfaceIDispatch .block

                                   {

          .block

                                       {

                                           j (0 = @$t0) '.printf /D "<b>\nUsing Interface IDispatch\n\n</b>"';'.printf /D "<b>\nNOT Using Interface IDispatch\n\n</b>"'

                                   }

         .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                                   {

                                       r @$t1 = poi(${obj}+0xC)

 

                                       .if(0 != @$t1)

       {

                                           r @$t2 = poi(${obj}+0x37)

                                           .if(0 = @$t0)

                                           {

                                               .if(@$t2 & 0x1)

                                               {

                                                   .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                                   !do @$t1

                              .printf "\n###############################################################################\n"

                                               }

                                           }

                                           .else

                                           {

                                               .if(0 = (@$t2 & 0x1))

                                               {

                                            .printf /D "<b>\nObject address: 0x%x\n</b>", ${obj}

                                                   !do @$t1

                                                   .printf "\n###############################################################################\n"

                                               }

                                           }

                                       }

                                   }

                               }

 

     }

     .block

     {

         as IsServerActivated .block

                              {

          .block

                                  {

                                      j (0 = @$t0) '.printf /D "<b>\nServer Is Activated\n\n</b>"';'.printf /D "<b>\nServer Is NOT Activated\n\n</b>"'

                                  }

                                  .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                                  {

                                      r @$t1 = poi(${obj}+0xC)

 

                                      .if(0 != @$t1)

                                      {

                                          r @$t2 = poi(${obj}+0x38)

                                          .if(0 = @$t0)

                                      {

                                              .if(@$t2 & 0x1)

                                              {

                                                  .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                       !do @$t1

                                                  .printf "\n###############################################################################\n"

                                              }

                                       }

                                          .else

                                          {

                                              .if(0 = (@$t2 & 0x1))

                                              {

                                           .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                                  !do @$t1

                                                  .printf "\n###############################################################################\n"

                                              }

                                          }

                                      }

                                  }

                              }

 

     }

     .block

     {

         as IsActive .block

                     {

          .block

                         {

                             j (0 = @$t0) '.printf /D "<b>\nIs Active\n\n</b>"';'.printf /D "<b>\nIs NOT Active\n\n</b>"'

                         }

    .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                         {

                             r @$t1 = poi(${obj}+0xC)

                             .if(0 != @$t1)

                             {

             r @$t2 = poi(${obj}+0x39)

                                 .if(0 = @$t0)

                                 {

                                     .if(@$t2 & 0x1)

                                     {

                                   .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                         !do @$t1

                                         .printf "\n###############################################################################\n"

         }

                                 }

                                 .else

                                 {

                                     .if(0 = (@$t2 & 0x1))

                                     {

                   .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                         !do @$t1

                                         .printf "\n###############################################################################\n"

                                     }

                                 }

                             }

                         }

                     }

     }

     .block

     {

         as IsFinalized .block

                        {

          .block

                            {

                                j (0 = @$t0) '.printf /D "<b>\nIs Finalized\n\n</b>"';'.printf /D "<b>\nIs NOT Finalized\n\n</b>"'

                            }

                            .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                            {

                         r @$t1 = poi(${obj}+0xC)

                                .if(0 != @$t1)

                                {

                                    r @$t2 = poi(${obj}+0x3B)

                                    .if(0 = @$t0)

                             {

                                        .if(@$t2 & 0x1)

                                        {

                                            .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                            !do @$t1

                                            .printf "\n###############################################################################\n"

                                        }

                                    }

                                 .else

                                    {

                                        .if(0 = (@$t2 & 0x1))

                                        {

                                            .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

          !do @$t1

                                            .printf "\n###############################################################################\n"

                                        }

                            }

                                }

                            }

                        }

     }

     .block

     {

         as ReturnedByFinalizer .block

                                {

          .block

                                    {

                                        j (0 = @$t0) '.printf /D "<b>\nReturned by Finalizer\n\n</b>"';'.printf /D "<b>\nNOT Returned by Finalizer\n\n</b>"'

                                    }

                      .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                                    {

                                        r @$t1 = poi(${obj}+0xC)

                                        .if(0 != @$t1)

                                        {

                                            r @$t2 = poi(${obj}+0x3B)

                                            .if(0 = @$t0)

                                            {

                                       .if(@$t2 & 0x1)

                                                {

                                                    .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                                    !do @$t1

                 .printf "\n###############################################################################\n"

                                                }

                                            }

                          .else

                                            {

                                                .if(0 = (@$t2 & 0x1))

                                                {

                                                    .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                                    !do @$t1

                                                    .printf "\n###############################################################################\n"

       }

                                            }

                                        }

                                    }

                                }

     }

     .block

     {

         as Disposed .block

                     {

          .block

                         {

                             j (0 = @$t0) '.printf /D "<b>\nDisposed\n\n</b>"';'.printf /D "<b>\nNOT Disposed\n\n</b>"'

                         }

      .foreach(obj { !dumpheap -type *ServicedComponentProxy -short })

                         {

                             r @$t1 = poi(${obj}+0xC)

                             .if(0 != @$t1)

                             {

               r @$t2 = poi(@$t1+0xD)

                                 .if(0 = @$t0)

                                 {

                                     .if(@$t2 & 0x1)

                                     {

                                        .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                         !do @$t1

                                         .printf "\n###############################################################################\n"

              }

                                 }

                                 .else

                                 {

                                     .if(0 = (@$t2 & 0x1))

                                     {

                                         .printf /D "<b>Object address: 0x%x\n</b>", ${obj}

                                         !do @$t1

                                         .printf "\n###############################################################################\n"

                                     }

                                 }

                             }

                         }

                     }

     }

}

.printf /D "\n\n<b>Select the filters below to see the Serviced Components that match the selection:</b>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${ObjectPooled} ad /q *; $$><${ScriptName}\"><b>Objects Pooled</b></link>"

.printf /D "\t\t\t\t<link cmd=\"r @$t0 = 1; ${ObjectPooled} ad /q *; $$><${ScriptName}\"><b>Objects NOT Pooled</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${IsJitActivated} ad /q *; $$><${ScriptName}\"><b>JIT Activated</b></link>"

.printf /D "\t\t\t\t<link cmd=\"r @$t0 = 1; ${IsJitActivated} ad /q *; $$><${ScriptName}\"><b>JIT NOT Activated</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${UseInterfaceIDispatch} ad /q *; $$><${ScriptName}\"><b>Using Interface IDispatch</b></link>"

.printf /D "\t\t<link cmd=\"r @$t0 = 1; ${UseInterfaceIDispatch} ad /q *; $$><${ScriptName}\"><b>NOT Using Interface IDispatch</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${IsServerActivated} ad /q *; $$><${ScriptName}\"><b>Server Is Activated</b></link>"

.printf /D "\t\t\t<link cmd=\"r @$t0 = 1; ${IsServerActivated} ad /q *; $$><${ScriptName}\"><b>Server Is NOT Activated</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${IsActive} ad /q *; $$><${ScriptName}\"><b>Is Active</b></link>"

.printf /D "\t\t\t\t\t<link cmd=\"r @$t0 = 1; ${IsActive} ad /q *; $$><${ScriptName}\"><b>Is NOT Active</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${IsFinalized} ad /q *; $$><${ScriptName}\"><b>Is Finalized</b></link>"

.printf /D "\t\t\t\t<link cmd=\"r @$t0 = 1; ${IsFinalized} ad /q *; $$><${ScriptName}\"><b>Is NOT Finalized</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${ReturnedByFinalizer} ad /q *; $$><${ScriptName}\"><b>Returned by Finalizer</b></link>"

.printf /D "\t\t\t<link cmd=\"r @$t0 = 1; ${ReturnedByFinalizer} ad /q *; $$><${ScriptName}\"><b>NOT Returned by Finalizer</b></link>\n\n"

.printf /D "<link cmd=\"r @$t0 = 0; ${Disposed} ad /q *; $$><${ScriptName}\"><b>Disposed Serviced Components</b></link>"

.printf /D "\t<link cmd=\"r @$t0 = 1; ${Disposed} ad /q *; $$><${ScriptName}\"><b>NOT Disposed Serviced Components</b></link>\n\n"

$$

Read me.