.NET Debugging : PowerDbg (part 2) - Send-PowerDbgCommand & Extending PowerDbg

12/26/2011 5:28:11 PM


Commands such as Analyze-PowerDbgThreads performs all the steps necessary to display the results of the command. In some cases, however, you may want to send an arbitrary command to the debugger and do your own post processing on the output of the command. In these cases, the Send-PowerDbgCommand can be used. The Send-PowerDbgCommand takes a string as an argument that includes the command you want to execute in the debugger. For example, if we want to run the kb 200 command, we would run the following:

PS C:\Windows\System32> Send-PowerDbgCommand "kb 200"

The net result of the command execution is a file called POWERDBGOUTPUT.LOG that contains the results. This file can then be used to do post processing of the command result and display the data in the most appropriate format. Because parsing the file can be cumbersome, PowerDbg also comes with a set of cmdlets called Parse-PowerDbg* where * is replaced by the equivalent debugger command. These commands take the file contents produced by the Send-PowerDbgCommandPOWERDBG-PARSED.LOG) where the content is nicely formatted and suitable to be used with the Convert-PowerDbgCSVToHashTable cmdlet, which converts it into a hash table for easier scripting. For example, the native debugger command ~* kpn 1000 (displays stack traces of all threads in the process) can be executed using the PowerDbg in the following fashion: cmdlet and create a new file (

PS C:\Windows\System32> Send-PowerDbgCommand "~* kpn 1000"
PS C:\Windows\System32> Parse-PowerDbgK
PS C:\Windows\System32> $ht = @{}
PS C:\Windows\System32> $ht = Convert-PowerDbgCSVToHashTable

The first command sends the ~*kpn 1000 command to the debugger, which runs the command and stores the results in the POWERDBG-OUTPUT.LOG. The Parse-PowerDbgK cmdlet then parses the results stored in that file and creates a new file called POWERDBG-PARSED.LOG, which is subsequently used by the Convert-PowerDbgCSVToHashTable cmdlet to return a hash table with the content of the parsed file. After we have the hash table, we can use it to display the different stack traces by using the write-host command:

PS C:\Windows\System32> write-host $ht["0"].Replace($global:g_frameDelimiter, "'n")
ChildEBP RetAddr
00 0017f060 778d8d94 ntdll!KiFastSystemCallRet
01 0017f064 778e9522 ntdll!NtRequestWaitReplyPort+0xc
02 0017f084 77507e05 ntdll!CsrClientCallServer+0xc2
03 0017f170 77507f35 KERNEL32!GetConsoleInput+0xd2
04 0017f190 001ca61c KERNEL32!ReadConsoleInputA+0x1a
Frame IP not in any known module. Following frames may be wrong.
05 0017f218 793e8f28 0x1ca61c
06 0017f280 793e8e33 mscorlib_ni+0x328f28
07 0017f2d0 79e7c6cc mscorlib_ni+0x328e33
08 0017f350 79e7c8e1 mscorwks!CallDescrWorkerWithHandler+0xa3
09 0017f490 79e7c783 mscorwks!MethodDesc::CallDescr+0x19c
0a 0017f4ac 79e7c90d mscorwks!MethodDesc::CallTargetWorker+0x1f
0b 0017f4c0 79eefb9e mscorwks!MethodDescCallSite::Call+0x18
0c 0017f624 79eef830 mscorwks!ClassLoader::RunMain+0x263
0d 0017f88c 79ef01da mscorwks!Assembly::ExecuteMainMethod+0xa6
0e 0017fd5c 79fb9793 mscorwks!SystemDomain::ExecuteMainMethod+0x43f
0f 0017fdac 79fb96df mscorwks!ExecuteEXE+0x59
10 0017fdf4 7900b1b3 mscorwks!_CorExeMain+0x15c
11 0017fe04 774a4911 mscoree!_CorExeMain+0x2c
12 0017fe10 778be4b6 KERNEL32!BaseThreadInitThunk+0xe
13 0017fe50 778be489 ntdll!__RtlUserThreadStart+0x23
14 0017fe68 00000000 ntdll!_RtlUserThreadStart+0x1b

PS C:\Windows\System32> write-host $ht["1"].Replace($global:g_frameDelimiter, "'n")
ChildEBP RetAddr
00 016ff95c 778d9244 ntdll!KiFastSystemCallRet
01 016ff960 774ac3e4 ntdll!ZwWaitForMultipleObjects+0xc
02 016ff9fc 774ac64e KERNEL32!WaitForMultipleObjectsEx+0x11d
03 016ffa18 79f4e8d8 KERNEL32!WaitForMultipleObjects+0x18
04 016ffa78 79f4e831 mscorwks!DebuggerRCThread::MainLoop+0xe9
05 016ffaa8 79f4e765 mscorwks!DebuggerRCThread::ThreadProc+0xe5
06 016ffad8 774a4911 mscorwks!DebuggerRCThread::ThreadProcStatic+0x9c
07 016ffae4 778be4b6 KERNEL32!BaseThreadInitThunk+0xe
08 016ffb24 778be489 ntdll!__RtlUserThreadStart+0x23
09 016ffb3c 00000000 ntdll!_RtlUserThreadStart+0x1b

Table 2 details the different Parse-PowerDbg* Cmdlets available.

Table 2. Parse-PowerDbg* cmdlets
Parse-PowerDbgDTParses the output from the dt command.
Parse-PowerDbgNAME2EEParses the output from the SOS name2ee command.
Parse-PowerDbgDUMPMDParses the output from the SOS dumpmd command.
Parse-PowerDbgDUMPMODULEParses the output from the SOS dumpmodule command.
Parse-PowerDbgLMIParses the output from the lm1 command.
Parse-PowerDbgVERTARGETParses the output from the vertarget command.
Parse-PowerDbgRUNAWAYParses the output from the runaway command.
Parse-PowerDbgKParses the output from the k command.
Parse-PowerDbgSymbolsFromKExtracts symbolic information from the k command.
Parse-PowerDbgLM1MParses the output from the lm1m command.
Parse-PowerDbgPRINTEXCEPTIONExtracts exception information.
Parse-PowerDbgDD-L1Parses the output from the dd command.
Parse-PowerDbgGCHANDLELEAKSParses the output from the SOS gchandleleaks command.
Parse-PowerDbgDUMPOBJParses the output from the SOS dumpobj command.

Extending PowerDbg

In addition to the plethora of cmdlets that the PowerDbg tool contains, it is also extremely easy to extend by utilizing the existing cmdlet source.

In this case, the teb command can be used, which displays all the data contained within the teb. Below is an example of the teb command:

0:004> !teb
TEB at 7ffda000
ExceptionList: 04a3f9a4
StackBase: 04a40000
StackLimit: 04a3c000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7ffda000
EnvironmentPointer: 00000000
ClientId: 0000196c . 000018ac
RpcHandle: 00000000
Tls Storage: 00000000
PEB Address: 7ffdb000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0

We can use the Send-PowerDbg command to send the teb command to the bugger and get the preceding results in the POWERDBG-OUTPUT.LOG. The next step is to implement the Parse-PowerDbgHandle command, which takes the results in POWERDBG-OUTPUT.LOG and massages them into a format suitable for the Convert-PowerDbgCSVToHashTable cmdlet and stores that result in POWERDBG-PARSED. LOG. We could then use the Convert-PowerDbgCSVToHashTable cmdlet to get the data into a hash table and manipulate it using other scripts. The majority of the work required is in implementing the Parse-PowerDbgHandle cmdlet, which is shown in Listing 1.

Listing 1. Parse-PowerDbgHandle cmdlet
function Parse-PowerDbgTEB()
set-psdebug -strict
$ErrorActionPreference = "stop"
trap {"Error message: $_"}

# Extract output removing commands.
$builder = New-Object System.Text.StringBuilder

# Title for the CSV fields.
$builder = $builder.AppendLine("key,value")

foreach($line in $(get-content $global:g_fileCommandOutput))
if($line.Contains("TEB at"))
$builder = $builder.AppendLine($f1 + $global:g_CSVDelimiter + $f2)

# Send output to our default file.
out-file -filepath $global:g_fileParsedOutput -inputobject "$builder"

The function walks each line in the raw data file and extracts each field’s name and value and appends each key value pair to a string. After all fields have been extracted, the string is written to the parsed output file. Subsequently, we can use the Convert-PowerDbgCSVtoHashTable to convert the parsed output file to a hash table as shown:

PS C:\> $h={}
PS C:\> $h=Convert-PowerDbgCSVtoHashTable

To see the values in the hash table, simply specify the hash table and PowerShell iterates through all the key pair values and displays them:

PS C:\> $h

Name Value
---- -----
LastErrorValue 0
ExceptionList 04a3f9a4
FiberData 00001e00
StackLimit 04a3c000
StackBase 04a40000
Count Owned Locks 0
RpcHandle 00000000
Self 7ffda000
LastStatusValue 0
HardErrorMode 0
SubSystemTib 00000000
ClientId 0000196c . 000018ac
PEB Address 7ffdb000
ArbitraryUserPointer 00000000
Tls Storage 00000000
EnvironmentPointer 00000000

The PowerDbg library is quite extensible and cmdlets can easily be created to reduce the time spent debugging certain categories of bugs by doing automatic analysis of debugger command output.

  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 3) - Configure Indexing & Performing a Search
  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 2) - Creating a Profile Page to Display BCS Results
  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 1) - Code-Based Solutions
  •  Sharepoint 2010 : BCS Architecture - Presentation & Core Components
  •  Collaborating via Web-Based Communication Tools : Evaluating Instant Messaging Services
  •  Collaborating via Web-Based Communication Tools : Evaluating Web Mail Services
  •  Developing the SAP Data Center : Data Center Physical Requirements
  •  Developing the SAP Data Center : Introducing the SAP Data Center
  •  Inventory of Broadband Phone Services
  •  Parallel Programming : Task Relationships (part 2) - Parent and Child Tasks
  •  Parallel Programming : Task Relationships (part 1) - Continuation Tasks
  •  BizTalk 2006 : Handling Ordered Delivery
  •  BizTalk 2006 : Implementing Dynamic Parallel Orchestrations
  •  Windows System Programming : The Registry
  •  Windows System Programming : File Locking
  •  SharePoint 2010 : Security - Secure Store Service & Using SSS with BCS
  •  SharePoint 2010 : Security - Claims Based Authentication
  •  SharePoint 2010 : PerformancePoint Services (part 2) - Using PerformancePoint
  •  SharePoint 2010 : PerformancePoint Services (part 1) - PerformancePoint Central Administration Settings
  •  Windows System Programming : Example: Listing File Attributes & Setting File Times
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)