Skip to content

Instantly share code, notes, and snippets.

@m-sedl
Created November 27, 2022 21:00
Show Gist options
  • Save m-sedl/cfc0dcd919145a5cc3077801d5225e07 to your computer and use it in GitHub Desktop.
Save m-sedl/cfc0dcd919145a5cc3077801d5225e07 to your computer and use it in GitHub Desktop.
using System.Reflection.Metadata;
using System.Text;
namespace Foo;
class TestSequencePointsIndex
{
private readonly Dictionary<string, List<SequencePoint>> _index = new ();
public FooClass(params string[] pdbPaths)
{
var documentPaths = new Dictionary<Document, string>();
foreach (var pdbPath in pdbPaths)
{
IndexPdbFile(pdbPath, documentPaths);
}
}
public List<int> FindOffsets(string sourceFilePath, int startLine, int startColumn)
{
if (!_index.ContainsKey(sourceFilePath))
{
return new List<int>();
}
var sf = _index[sourceFilePath];
return sf.Where(sp => sp.StartLine == startLine).Select(sp => sp.Offset).ToList();
}
private void IndexPdbFile(string pdbPath, Dictionary<Document, string> documentPaths)
{
using var fs = new FileStream(pdbPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var provider = MetadataReaderProvider.FromPortablePdbStream(fs);
var reader = provider.GetMetadataReader();
foreach (var di in reader.MethodDebugInformation)
{
var mdi = reader.GetMethodDebugInformation(di);
if (mdi.Document.IsNil) continue;
var doc = reader.GetDocument(mdi.Document);
if (!documentPaths.ContainsKey(doc))
{
var path = ReadDocumentPath(reader, doc);
documentPaths[doc] = path;
_index[path] = new List<SequencePoint>();
}
var notHiddenPoints = mdi.GetSequencePoints().Where(sp => !sp.IsHidden);
var sourceFilePath = documentPaths[doc];
_index[sourceFilePath].AddRange(notHiddenPoints);
}
}
private static string ReadDocumentPath(MetadataReader reader, Document doc)
{
var blob = reader.GetBlobReader(doc.Name);
// Read path separator character
var separator = (char)blob.ReadByte();
var sb = new StringBuilder(blob.Length * 2);
// Read path segments
while (true)
{
var bh = blob.ReadBlobHandle();
if (!bh.IsNil)
{
var nameBytes = reader.GetBlobBytes(bh);
sb.Append(Encoding.UTF8.GetString(nameBytes));
}
if (blob.Offset >= blob.Length) break;
sb.Append(separator);
}
return sb.ToString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment