Determining source line given knowledge of Metadata token describing method and IL offset

Topics: PDB Reader
Jun 27, 2012 at 6:46 PM

I am writing a custom debugger for IL programs on a homebrew operating system.  I am able to single-step through machine code and at each step can determine the module name, metadata token and il offset of each machine code instruction but am having difficulty trying to convert this into a c# source offset using cci metadata.

 

I generate a pdb file from vs2010 and load this with PdbReader having previously loaded the pe file for the assembly into the DefaultHost MetadataReaderHost (I am not sure if this step is completely necessary).  At this point, I can get the information I need using the private members of PdbReader (namely pdbFunctionMap[metadata_token] and then iterating through the lines members) but cannot see a way to get this information through the public interfaces of cci metadata.  In particular, the GetPrimarySourceLocationsForToken() function does not work as the tokenToSourceMapping dictionary is not filled as the "TokenSourceLineInfo" module is not found in PdbFile.LoadFunctions().  Unfortunately I do not understand the format of the pdb file sufficiently to take this debugging further.

 

Adding the following to SourceLocationProvider.cs provides the functionality I want, but I am wondering if there is a way of getting this information without having to modify the sources.

 

    /// <summary>
    /// Returns zero or more locations for the source for a given method represented by a metadata token.</summary>
    /// </summary>
    /// <param name="token">metadata token representing a method</param>
    /// <returns>an IDictionary<> linking an il offset to a source file location</returns>
    public IDictionary<uint, IPrimarySourceLocation> GetPrimarySourceLocationsForMethodToken(uint token)
    {
        Dictionary<uint, IPrimarySourceLocation> ret = new Dictionary<uint, IPrimarySourceLocation>();
        PdbFunction function;
        if (!this.pdbFunctionMap.TryGetValue(token, out function)) return ret;
        foreach (PdbLines lines in function.lines)
        {
            PdbSourceDocument psDoc = this.GetPrimarySourceDocumentFor(lines.file);
            foreach (PdbLine line in lines.lines)
                ret.Add(line.offset, new PdbSourceLineLocation(psDoc, (int)line.lineBegin, (int)line.colBegin, (int)line.lineEnd, (int)line.colEnd));
        }
        return ret;
    }

Regards,

John.

Coordinator
Jun 28, 2012 at 5:28 PM

Your scenario is not currently supported by the public API of PdbReader. If you wish to submit your addition as a patch, I'll be happy to add it to the source tree.

Jun 28, 2012 at 9:07 PM

Thank you.  I have submitted it as a patch with mildly modified documentation tags to allow the help file to build properly.

Regards,

John.