A code snippet used to explorer symbols of a pdb file.
using System;
using System.Collections.Generic;
using System.Linq;
using Dia2Lib;
namespace PDBParser
{
class PDBExplorer
{
private Stack<IDiaSymbol> _accessStack = new Stack<IDiaSymbol>();
public IDiaSymbol RootSymbol { get; private set; }
public IDiaSession Session { get; private set; }
public string PdbPath { get; private set; }
public IDiaSymbol CurrentSymbol { get; private set; }
public PDBExplorer(string path)
{
PdbPath = path;
}
public int Deepth
{
get => _accessStack.Count;
}
public void Open()
{
var proxy = new DiaSourceClass();
proxy.loadDataFromPdb(PdbPath);
proxy.openSession(out var session);
RootSymbol = session.globalScope;
Session = session;
CurrentSymbol = RootSymbol;
}
public IDiaEnumSymbols List(SymTagEnum type, string name, bool adapt = true)
{
try
{
if (adapt)
{
CurrentSymbol.findChildrenEx(type, name, name == null ? 0u : 8u, out var symbols);
return symbols;
}
else
{
CurrentSymbol.findChildrenEx(type, name, 0u, out var symbols);
return symbols;
}
}
catch (NotImplementedException)
{
return null;
}
}
public IDiaSymbol ReturnLastLayer()
{
if (_accessStack.Count > 0)
{
CurrentSymbol = _accessStack.Pop();
}
return CurrentSymbol;
}
public bool GetInSymbol(SymTagEnum type, string name)
{
var symbols = List(type, name, false);
if (symbols is null)
{
return false;
}
foreach (IDiaSymbol diaSymbol in symbols)
{
if ((SymTagEnum)diaSymbol.symTag == type && diaSymbol.name == name)
{
_accessStack.Push(CurrentSymbol);
CurrentSymbol = diaSymbol;
return true;
}
}
return false;
}
public bool GetInSymbol(uint id)
{
try
{
Session.symbolById(id, out var symbol);
if (symbol is null)
return false;
else
{
_accessStack.Push(CurrentSymbol);
CurrentSymbol = symbol;
return true;
}
}
catch (Exception)
{
return false;
}
}
public IList<IDiaSymbol> GetSymbolStack()
{
Stack<IDiaSymbol> temp = new Stack<IDiaSymbol>();
List<IDiaSymbol> result = new List<IDiaSymbol>();
while (_accessStack.Count > 0)
{
temp.Push(_accessStack.Pop());
}
while (temp.Count > 0)
{
result.Add(temp.Peek());
_accessStack.Push(temp.Pop());
}
result.Add(CurrentSymbol);
return result;
}
}
class PdbMonitor
{
private PDBExplorer explorer;
public PdbMonitor(PDBExplorer explorer)
{
this.explorer = explorer;
}
public void StartLoop()
{
explorer.Open();
DisplayItem(explorer.RootSymbol);
foreach (var b in loopBody())
{
if (b) return;
}
}
private IEnumerable<bool> loopBody()
{
while (true)
{
yield return ProcessCommand(ReadCommand());
}
}
public void DisplayItem(IDiaSymbol symbol)
{
Console.WriteLine(FormatSymbol(symbol));
}
public string FormatSymbol(IDiaSymbol symbol)
{
return $"[{(SymTagEnum)symbol.symTag}:{symbol.symIndexId}] {symbol.name}";
}
public IList<string> ReadCommand()
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.Write('>');
Console.ForegroundColor = ConsoleColor.DarkGreen;
var commandContent = Console.ReadLine();
Console.ForegroundColor = ConsoleColor.Gray;
return (from subString in commandContent.Split(' ') select subString.Trim()).ToArray();
}
private bool ProcessCommand(IList<string> command)
{
switch (command[0])
{
case "current":
case "ps":
{
var symbols = explorer.GetSymbolStack();
for (var i = 0; i != symbols.Count; i++)
{
for(var j = 0; j != i; j++)
Console.Write("----");
DisplayItem(symbols[i]);
}
break;
}
case "upward":
case "back":
{
DisplayItem(explorer.ReturnLastLayer());
break;
}
case "sc":
case "cd":
{
if (command.Count < 3)
{
if (command.Count == 2 && command[1] == "..")
{
ProcessCommand(new []{"back"});
break;
}
Console.WriteLine("Must pass type and name of symbol you want to enter.");
break;
}
if (!Enum.TryParse(command[1], true, out SymTagEnum tagEnum))
{
if (!Enum.TryParse("SymTag" + command[1], true, out tagEnum))
tagEnum = SymTagEnum.SymTagNull;
}
var succeed = explorer.GetInSymbol(tagEnum, command[2]);
if(succeed)
DisplayItem(explorer.CurrentSymbol);
else
Console.WriteLine("No symbol found.");
break;
}
case "sci":
case "cdi":
{
if (command.Count < 2)
{
Console.WriteLine("Must pass index of symbol you want to enter.");
break;
}
if (uint.TryParse(command[1], out uint id))
{
var succeed = explorer.GetInSymbol(id);
if (succeed)
DisplayItem(explorer.CurrentSymbol);
else
Console.WriteLine("No symbol found.");
}
else
{
Console.WriteLine("No symbol found.");
}
break;
}
case "list":
case "ls":
{
var tagEnum = SymTagEnum.SymTagNull;
if (command.Count > 1)
{
if (!Enum.TryParse(command[1], true, out tagEnum))
{
if (!Enum.TryParse("SymTag" + command[1], true, out tagEnum))
tagEnum = SymTagEnum.SymTagNull;
}
}
string name = null;
if (command.Count > 2)
name = command[2].ToLower();
var symbols = explorer.List(tagEnum, name);
if (symbols is null)
{
Console.WriteLine("No Children Node Symbol Found.");
}
else
{
int num = 0;
foreach (IDiaSymbol symbol in symbols)
{
DisplayItem(symbol);
num++;
}
Console.WriteLine(num > 0 ? $"{num} Symbols Found." : "No Children Node Symbol Found.");
}
break;
}
case "quit":
{
return true;
}
default:
{
Console.WriteLine("Cannot parse command.");
break;
}
}
return false;
}
}
}