/// <summary> /// Load the PDB given the parameters at the ctor and spew it out to the XmlWriter specified /// at the ctor. /// </summary> public SymbolData ReadSymbols() { // Actually load the files var reader = SymbolAccess.GetReaderForFile(symFormat, assemblyPath, null); if (reader == null) { Console.WriteLine("Error: No matching PDB could be found for the specified assembly."); return(null); } AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve); assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(assemblyPath); fileMapping = new Dictionary <string, int>(); var symbolData = new SymbolData(); // Record what input file these symbols are for. symbolData.assembly = assemblyPath; symbolData.moduleVersion = assembly.ManifestModule.ModuleVersionId; symbolData.entryPointToken = ReadEntryPoint(reader); symbolData.sourceFiles = ReadDocList(reader); if (!skipMethods) { symbolData.methods = ReadAllMethods(reader); } return(symbolData); }
public void WritePdb(SymbolData symData) { m_docWriters = new Dictionary <int, ISymbolDocumentWriter>(); ImageDebugDirectory debugDirectory; byte[] debugInfo = null; // Rather than use the emitter here, we are just careful enough to emit pdb metadata that // matches what is already in the assembly image. object emitter = null; // We must be careful to close the writer before updating the debug headers. The writer has an // open file handle on the assembly we want to update. m_writer = SymbolAccess.GetWriterForFile(m_symFormat, m_outputAssembly, ref emitter); // We don't actually need the emitter in managed code at all, so release the CLR reference on it Marshal.FinalReleaseComObject(emitter); try { WriteEntryPoint(symData.entryPointToken); WriteFiles(symData.sourceFiles); WriteMethods(symData.methods); debugInfo = m_writer.GetDebugInfo(out debugDirectory); } finally { m_writer.Close(); ((IDisposable)m_writer).Dispose(); m_writer = null; m_docWriters.Clear(); } UpdatePEDebugHeaders(debugInfo); }
public void Convert() { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("symbols"); xmlWriter.WriteAttributeString("program", "PdbConvert"); xmlWriter.WriteAttributeString("version", "1"); AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; string currDir = Environment.CurrentDirectory; foreach (string fileName in assemblyFileNames) { // Change to the file's directory so that we can find referenced assemblies Environment.CurrentDirectory = Path.GetDirectoryName(fileName); ISymbolReader reader = SymbolAccess.GetReaderForFile(fileName); assembly = Assembly.ReflectionOnlyLoadFrom(fileName); xmlWriter.WriteStartElement("module"); xmlWriter.WriteAttributeString("file", Path.GetFileName(fileName).ToLowerInvariant()); xmlWriter.WriteAttributeString("version", GetAssemblyVersion(assembly)); xmlWriter.WriteAttributeString("config", GetAssemblyConfiguration(assembly)); WriteDocList(reader); //WriteEntryPoint(reader); WriteAllMethods(reader); xmlWriter.WriteEndElement(); // </module> } Environment.CurrentDirectory = currDir; AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= CurrentDomain_ReflectionOnlyAssemblyResolve; xmlWriter.WriteEndElement(); // </symbols> }
public void Convert() { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("symbols"); xmlWriter.WriteAttributeString("program", "PdbConvert"); xmlWriter.WriteAttributeString("version", "1"); AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; string currDir = Environment.CurrentDirectory; foreach (string fileName in assemblyFileNames) { // Change to the file's directory so that we can find referenced assemblies Environment.CurrentDirectory = Path.GetDirectoryName(fileName); ISymbolReader reader = SymbolAccess.GetReaderForFile(fileName); if (reader == null) { ConsoleHelper.WriteLine("Warning: Cannot read symbols for: " + fileName, ConsoleColor.Yellow); try { DateTime asmTime = new FileInfo(fileName).LastWriteTimeUtc; DateTime symTime = new FileInfo(Path.ChangeExtension(fileName, ".pdb")).LastWriteTimeUtc; if (Math.Abs((asmTime - symTime).TotalSeconds) > 10) { ConsoleHelper.WriteLine(" Hint: .pdb file time does not match assembly file time. Either delete or update the symbols file.", ConsoleColor.Yellow); } } catch { // Ignore errors } } else { assembly = Assembly.ReflectionOnlyLoadFrom(fileName); xmlWriter.WriteStartElement("module"); xmlWriter.WriteAttributeString("file", Path.GetFileName(fileName).ToLowerInvariant()); xmlWriter.WriteAttributeString("version", GetAssemblyVersion(assembly)); xmlWriter.WriteAttributeString("config", GetAssemblyConfiguration(assembly)); WriteDocList(reader); //WriteEntryPoint(reader); WriteAllMethods(reader); xmlWriter.WriteEndElement(); // </module> } } Environment.CurrentDirectory = currDir; AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= CurrentDomain_ReflectionOnlyAssemblyResolve; xmlWriter.WriteEndElement(); // </symbols> }
// Maps files to ids. /// <summary> /// Load the PDB given the parameters at the ctor and spew it out to the XmlWriter specified /// at the ctor. /// </summary> internal void ReadPdbAndWriteToXml() { // Actually load the files // Dynamically discover if there is ISymbolReader reader = null; // Calling OpenScope on a pdb throws a COMException for CLDB_E_FILE_CORRUPT // If they passed a pdb file, we'll try for the exe or dll here in a sec if (String.Compare(Path.GetExtension(m_fileName), ".pdb", StringComparison.OrdinalIgnoreCase) != 0) { reader = SymbolAccess.GetReaderForFile(m_fileName); } if (reader == null) { m_fileName = Path.ChangeExtension(m_fileName, ".exe"); if (File.Exists(m_fileName)) { reader = SymbolAccess.GetReaderForFile(m_fileName); } } if (reader == null) { m_fileName = Path.ChangeExtension(m_fileName, ".dll"); if (File.Exists(m_fileName)) { reader = SymbolAccess.GetReaderForFile(m_fileName); } } if (reader == null) { Console.WriteLine("Error: No Symbol Reader could be initialized."); return; } AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; m_assembly = Assembly.ReflectionOnlyLoadFrom(m_fileName); // Begin writing XML. m_writer.WriteStartDocument(); m_writer.WriteComment("This is an XML file representing the PDB for '" + m_fileName + "'"); m_writer.WriteStartElement("symbols"); // Record what input file these symbols are for. m_writer.WriteAttributeString("file", m_fileName); WriteDocList(reader); WriteEntryPoint(reader); WriteAllMethods(reader); m_writer.WriteEndElement(); // "Symbols"; }
public VariableInfo[] Read(MethodInfo info) { var il = info.GetMethodBody().LocalVariables.ToArray(); return(SymbolAccess .GetReaderForFile(info.DeclaringType.Assembly.Location) .GetMethod(new SymbolToken(info.MetadataToken)) .RootScope .GetInnerScopesRecursive() .SelectMany(scope => scope.GetLocals()) .Select(local => new VariableInfo(local.AddressField1, il[local.AddressField1].LocalType, local.Name)) .ToArray()); }
private ISymbolReader TryGetSymbolReader(Assembly assembly) { const int E_PDB_NO_DEBUG_INFO = unchecked ((int)0x806D0014); try { return(SymbolAccess.GetReaderForFile(assembly.Location)); } catch (COMException ex) { if (ex.ErrorCode == E_PDB_NO_DEBUG_INFO) { return(null); } throw; } }
internal Xml2PdbConverter(XmlDocument doc, string OutputAssembly) { m_doc = doc; m_docWriters = new Dictionary <int, ISymbolDocumentWriter>(); m_sequencePoints = new Dictionary <int, List <int>[]>(); string ext = Path.GetExtension(m_doc.DocumentElement.GetAttribute("file")); m_outputAssembly = Path.ChangeExtension(OutputAssembly, ext); object emitter = null; m_writer = SymbolAccess.GetWriterForFile(m_outputAssembly, ref emitter); // Rather than use the emitter here, we are just careful enough to emit pdb metadata that // matches what is already in the assembly image. }
/// <summary> /// Creates a <see cref="ISymbolReader"/> for the given <paramref name="assembly"/>. /// </summary> /// <param name="assembly">The assembly whose reader is needed.</param> /// <returns>The <see cref="ISymbolReader"/> instance or <c>null</c> if one cannot be created (e.g. no PDB).</returns> private ISymbolReader CreateSymbolReader(Assembly assembly) { Debug.Assert(assembly != null, "The assembly is required"); ISymbolReader reader = null; string assemblyFile = assembly.Location; try { reader = SymbolAccess.GetReaderForFile(assemblyFile, this._symbolSearchPath); } catch (System.Runtime.InteropServices.COMException cex) { // Experience has shown some large PDB's can exhaust memory and cause COM failures. // When this occurs, we log a warning and continue as if the PDB was not there. if (this._logger != null) { this._logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Open_PDB, assemblyFile, cex.Message)); } } return(reader); }
public SourceInfos GetSourceInfos(UInt32 aAddress) { var xResult = new SourceInfos(); try { var xMethod = GetMethod(aAddress); if (xMethod != null) { var xSymbols = GetSymbols(xMethod); var xAssemblyFile = mConnection.Get <AssemblyFile>(xMethod.AssemblyFileID); var xSymbolReader = SymbolAccess.GetReaderForFile(xAssemblyFile.Pathname); var xMethodSymbol = xSymbolReader.GetMethod(new SymbolToken(xMethod.MethodToken)); int xSeqCount = xMethodSymbol.SequencePointCount; var xCodeOffsets = new int[xSeqCount]; var xCodeDocuments = new ISymbolDocument[xSeqCount]; var xCodeLines = new int[xSeqCount]; var xCodeColumns = new int[xSeqCount]; var xCodeEndLines = new int[xSeqCount]; var xCodeEndColumns = new int[xSeqCount]; xMethodSymbol.GetSequencePoints(xCodeOffsets, xCodeDocuments, xCodeLines, xCodeColumns, xCodeEndLines, xCodeEndColumns); if (xSymbols.Length == 0 && xSeqCount > 0) { var xSourceInfo = new SourceInfo() { SourceFile = xCodeDocuments[0].URL, Line = xCodeLines[0], LineEnd = xCodeEndLines[0], Column = xCodeColumns[0], ColumnEnd = xCodeEndColumns[0], MethodName = xMethod.LabelCall }; xResult.Add(aAddress, xSourceInfo); } else { foreach (var xSymbol in xSymbols) { var xRow = mConnection.Query <Label>(new SQLinq <Label>().Where(i => i.Name == xSymbol.LabelName)).FirstOrDefault(); if (xRow != null) { UInt32 xAddress = (UInt32)xRow.Address; // Each address could have mult labels, but this wont matter for SourceInfo, its not tied to label. // So we just ignore duplicate addresses. if (!xResult.ContainsKey(xAddress)) { int xIdx = SourceInfo.GetIndexClosestSmallerMatch(xCodeOffsets, xSymbol.IlOffset); var xSourceInfo = new SourceInfo() { SourceFile = xCodeDocuments[xIdx].URL, Line = xCodeLines[xIdx], LineEnd = xCodeEndLines[xIdx], Column = xCodeColumns[xIdx], ColumnEnd = xCodeEndColumns[xIdx], MethodName = xMethod.LabelCall }; xResult.Add(xAddress, xSourceInfo); } } } } } } catch (Exception) { } return(xResult); }