|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DiaTool
{
internal class ModuleInfo
{
public ModuleInfo(UInt64 baseAddress, UInt64 endAddress, string moduleName, string pdbName)
{
if (endAddress < baseAddress)
{
throw new Exception("ModuleInfo() endAddress < baseAddress is not allowed.");
}
m_baseAddress = baseAddress;
m_endAddress = endAddress;
m_moduleName = moduleName;
m_pdbName = pdbName;
}
public UInt64 BaseAddress
{
get { return m_baseAddress; }
}
public UInt64 EndAddress
{
get { return m_endAddress; }
}
public string ModuleName
{
get { return m_moduleName; }
}
public string PdbName
{
get { return m_pdbName; }
}
public bool Contains(UInt64 address)
{
if ((m_baseAddress <= address) && (address <= m_endAddress))
{
return true;
}
else
{
return false;
}
}
private UInt64 m_baseAddress;
private UInt64 m_endAddress;
private string m_moduleName;
private string m_pdbName;
}
public class Dia
{
public Dia(List<string> filesToProcess, List<string> filesToAnalyze, string outputFile)
{
m_filesToProcess = filesToProcess;
m_filesToAnalyze = filesToAnalyze;
m_outputFile = outputFile;
m_addressTable = new Dictionary< string, Dictionary<UInt64, string > >();
}
public void Process()
{
if (m_filesToProcess.Count == 0)
{
// Don't bother
return;
}
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(m_outputFile))
{
for (int i = 0; i < m_filesToProcess.Count; i++)
{
string pdbPath = m_filesToProcess[i];
string pdbName = System.IO.Path.GetFileName(pdbPath);
Dia2Lib.DiaSourceClass dia = new Dia2Lib.DiaSourceClass();
dia.loadDataFromPdb(pdbPath);
Dia2Lib.IDiaSession session;
dia.openSession(out session);
Dia2Lib.IDiaSymbol globalScope = session.globalScope;
uint machineType = globalScope.machineType;
Dictionary< UInt64, string > addressTable = new Dictionary< UInt64, string >();
m_addressTable.Add(pdbName, addressTable);
Dia2Lib.IDiaEnumSymbols result;
session.findChildren(null, Dia2Lib.SymTagEnum.SymTagNull, null, 0, out result);
globalScope.findChildren(Dia2Lib.SymTagEnum.SymTagNull, null, 0, out result);
foreach (Dia2Lib.IDiaSymbol symbol in result)
{
if (symbol.function != 0)
{
if (addressTable.ContainsKey(symbol.relativeVirtualAddress) == true)
{
string name = addressTable[symbol.relativeVirtualAddress];
if (name != symbol.name)
{
//throw new Exception("Address with multiple symbol names");
// happended with std::logic_error, need to be investigated further
// ??_Glogic_error@std@@UAEPAXI@Z
// ??_Elogic_error@std@@UAEPAXI@Z
continue;
} else
{
continue;
}
}
addressTable.Add(symbol.relativeVirtualAddress, symbol.undecoratedName);
writer.WriteLine("{0:X8}\t{1}\t{2}", symbol.relativeVirtualAddress, pdbName, symbol.undecoratedName);
}
}
}
}
}
public void Analyze()
{
if (m_filesToProcess.Count == 0)
{
// Don't bother
return;
}
if (m_filesToAnalyze.Count == 0)
{
// Don't bother
return;
}
for (int i = 0; i < m_filesToAnalyze.Count; i++)
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(m_filesToAnalyze[i]))
{
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(m_filesToAnalyze[i] + ".anl"))
{
// Search for mark point for modules list
while (reader.EndOfStream == false)
{
string line = reader.ReadLine().ToLower();
if (line.Contains("start modules dump") == true)
{
break;
}
}
// Read modules info
m_moduleInfo = new List<ModuleInfo>();
while (reader.EndOfStream == false)
{
string line = reader.ReadLine().ToLower();
if (line.Contains("end modules dump") == true)
{
break;
}
// "0x12345678 - 0x87654321 ModuleName"
UInt64 baseAddress = System.UInt64.Parse(line.Substring(2, 8) /* skip "0x" */, System.Globalization.NumberStyles.AllowHexSpecifier);
UInt64 endAddress = System.UInt64.Parse(line.Substring(15, 8) /* skip "0x" */, System.Globalization.NumberStyles.AllowHexSpecifier);
string moduleName = line.Substring(27);
string pdbName = null;
foreach (string file in m_filesToProcess)
{
if (file.Contains(System.IO.Path.GetFileNameWithoutExtension(moduleName)) && (System.IO.File.Exists(file) == true))
{
pdbName = file;
break;
}
}
m_moduleInfo.Add(new ModuleInfo(baseAddress, endAddress, moduleName, pdbName));
}
// Search for mark point for stack dump
while (reader.EndOfStream == false)
{
string line = reader.ReadLine().ToLower();
if (line.Contains("start stack dump") == true)
{
break;
}
}
// Find and extend info
while (reader.EndOfStream == false)
{
string line = reader.ReadLine().ToLower();
if (line.Contains("end stack dump") == true)
{
break;
}
UInt64 address = System.UInt64.Parse(line.Substring(2, 8) /* skip "0x" */, System.Globalization.NumberStyles.AllowHexSpecifier);
bool found = false;
// Now try to match the address in a module
foreach (ModuleInfo moduleInfo in m_moduleInfo)
{
if (moduleInfo.Contains(address) == true)
{
if (moduleInfo.PdbName == null)
{
// We have no more info for it, though we now where it came from
writer.WriteLine(line + " - " + moduleInfo.ModuleName + " : ----------");
found = true;
break;
}
UInt64 moduleAddress = address - moduleInfo.BaseAddress;
Dia2Lib.DiaSourceClass dia = new Dia2Lib.DiaSourceClass();
dia.loadDataFromPdb(moduleInfo.PdbName);
Dia2Lib.IDiaSession session;
dia.openSession(out session);
Dia2Lib.IDiaSymbol diaSymbol = null;
session.findSymbolByRVA((UInt32)moduleAddress, Dia2Lib.SymTagEnum.SymTagNull, out diaSymbol);
if (diaSymbol != null)
{
// Found!!
if (moduleAddress == diaSymbol.relativeVirtualAddress)
{
string name = (diaSymbol.undecoratedName != null) ? diaSymbol.undecoratedName : diaSymbol.name;
writer.WriteLine(line + " - " + moduleInfo.ModuleName + " : " + name);
}
else
{
// We have no direct info, what about its parent?
diaSymbol = diaSymbol.lexicalParent;
string name = (diaSymbol.undecoratedName != null) ? diaSymbol.undecoratedName : diaSymbol.name;
writer.WriteLine(line + " - " + moduleInfo.ModuleName + " : [" + name + "]");
}
found = true;
break;
}
}
}
if (found == false)
{
// Not found?
writer.WriteLine(line + " : ----------");
}
}
}
}
}
}
private List<string> m_filesToProcess;
private List<string> m_filesToAnalyze;
private string m_outputFile;
// pdb, address, source
private Dictionary< string, Dictionary< UInt64, string > > m_addressTable;
private List<ModuleInfo> m_moduleInfo;
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.