Demo for Pdb2Xml round-tripping
Overview:
The Pdb2Xml tool can convert a pdb file into xml, allow you to edit the xml, and then convert back to a pdb file.
Pdbs for managed code generally hold the source to IL mappings and the name of the local variables. Pdbs can be created and viewed with the com-classic CorSym APIs. MDbg provides managed wrappers for these APIs in corapi\sym*.
This tool originally started with this blog entry about converting Pdb to Xml, and then was expanded to convert Xml back to Pdbs.
Demo:
1) Start with a simple test.cs file:
using System;
class MyTest
{
static void Main()
{
int myLocal = 5;
Console.WriteLine("Hi");
Console.WriteLine("Value:" + myLocal);
}
}
2) Compile it.
csc test.cs /debug+
This should produce both test.exe and test.pdb.
3) Run it under a debugger and we see:
mdbg> run test.exe
STOP: Breakpoint Hit
6:{
[p#:0, t#:0] mdbg> sh 10
1 using System;
2
3 class MyTest
4 {
5 static void Main()
6:*{
7 int myLocal = 5;
8 Console.WriteLine("Hi");
9 Console.WriteLine("Value:" + myLocal);
10 }
[p#:0, t#:0] mdbg> print
myLocal=0
[p#:0, t#:0] mdbg>
4) Run the pdb2xml tool to convert the pdb to an xml file.
..\..\bin\Debug\pdb2xml.exe test.exe a.xml
The xml file looks like:
<!--This is an XML file representing the PDB for 'test.exe'--> <symbols file="test.exe"> <!--This is a list of all source files referred by the PDB.--> <files> <file id="1" name="c:\dev\mdbg_Sample3\mdbg\demo\pdb2xml\test.cs" language="3f5162f8-07c6-11d3-9053-00c04fa302a1" languageVendor="994b45c4-e6e9-11d2-903f-00c04fa302a1" documentType="5a869d0b-6611-11d3-bd2a-0000f80849bd" /> </files> <!--This is the token for the 'entry point' method, which is the method that will be called when the assembly is loaded. This usually corresponds to 'Main'--> <EntryPoint> <methodref>0x6000001</methodref> </EntryPoint> <!--This is a list of all methods in the assembly that matches this PDB.--> <!--For each method, we provide the sequence tables that map from IL offsets back to source.--> <methods> <method name="MyTest.Main" token="0x6000001" localSigMetadataToken="0x11000001"> <sequencepoints total="5"> <entry il_offset="0x0" start_row="6" start_column="1" end_row="6" end_column="2" file_ref="1" /> <entry il_offset="0x1" start_row="7" start_column="2" end_row="7" end_column="18" file_ref="1" /> <entry il_offset="0x3" start_row="8" start_column="2" end_row="8" end_column="26" file_ref="1" /> <entry il_offset="0xe" start_row="9" start_column="2" end_row="9" end_column="40" file_ref="1" /> <entry il_offset="0x24" start_row="10" start_column="1" end_row="10" end_column="2" file_ref="1" /> </sequencepoints> <locals> <local name="myLocal" il_index="0" il_start="0x0" il_end="0x25" attributes="0" signature="08" /> </locals> <scope startOffset="0x0" endOffset="0x25"> <local name="myLocal" il_index="0" il_start="0x0" il_end="0x25" attributes="0" signature="08" /> </scope> </method> </methods> </symbols>
5) Edit the xml file.
We can now edit the XML file and convert it back to a pdb. First we'll just rename the local:
<locals> <local name="myNewLocal" il_index="0" il_start="0x0" il_end="0x25" attributes="0" signature="08" /> </locals> <scope startOffset="0x0" endOffset="0x25"> <local name="myNewLocal" il_index="0" il_start="0x0" il_end="0x25" attributes="0" signature="08" /> </scope>
6) Convert back from xml to pdb.
C:\dev\mdbg_Sample3\mdbg\demo\pdb2xml>..\..\bin\Debug\pdb2xml.exe /reverse edit_local.xml test.exe
Test harness for PDB2XML.
This will update the executable image (test.exe) because an exe contains a stamp for the pdb. When the pdb is changed, the exe's stamp must be updated.
7) Now when we run under a debugger, we see the local is updated.
run test.exe
STOP: Breakpoint Hit
6:{
sh
3 class MyTest
4 {
5 static void Main()
6:*{
7 int myLocal = 5;
8 Console.WriteLine("Hi");
print
myNewLocal=0
We can also reassign source mappings.