void OnUpdateModuleSymbols(object sender, CorUpdateModuleSymbolsEventArgs e) { SymbolBinder binder = new SymbolBinder(); CorMetadataImport mi = new CorMetadataImport(e.Module); ISymbolReader reader = binder.GetReaderFromStream(mi.RawCOMObject, e.Stream); foreach (ISymbolDocument doc in reader.GetDocuments()) { Console.WriteLine(doc.URL); } e.Continue = true; }
public static ISymbolReader GetSymbolReaderForFile(SymbolBinder binder, string pathModule, string searchPath) { // Guids for imported metadata interfaces. Guid dispenserClassID = new Guid(0xe5cb7a31, 0x7512, 0x11d2, 0x89, 0xce, 0x00, 0x80, 0xc7, 0x92, 0xe5, 0xd8); // CLSID_CorMetaDataDispenser Guid dispenserIID = new Guid(0x809c652e, 0x7396, 0x11d2, 0x97, 0x71, 0x00, 0xa0, 0xc9, 0xb4, 0xd5, 0x0c); // IID_IMetaDataDispenser Guid importerIID = new Guid(0x7dac8207, 0xd3ae, 0x4c75, 0x9b, 0x67, 0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44); // IID_IMetaDataImport // First create the Metadata dispenser. object objDispenser; NativeMethods.CoCreateInstance(ref dispenserClassID, null, 1, ref dispenserIID, out objDispenser); // Now open an Importer on the given filename. We'll end up passing this importer straight // through to the Binder. object objImporter; IMetaDataDispenser dispenser = (IMetaDataDispenser)objDispenser; dispenser.OpenScope(pathModule, 0, ref importerIID, out objImporter); IntPtr importerPtr = IntPtr.Zero; ISymbolReader reader; try { // This will manually AddRef the underlying object, so we need to be very careful to Release it. importerPtr = Marshal.GetComInterfaceForObject(objImporter, typeof(IMetadataImport)); reader = binder.GetReader(importerPtr, pathModule, searchPath); } finally { if (importerPtr != IntPtr.Zero) { Marshal.Release(importerPtr); } } return(reader); }
private ArrayType GetArrayType(PapyrusType elementType) { var objectIdentifier = elementType.Name; lock (_arrayTypes) { if (!_arrayTypes.ContainsKey(objectIdentifier)) { var source = CreateArrayTypeSource(objectIdentifier); var stream = new CaseInsensitiveStringStream(source); var lexer = new PapyrusLexer(stream); var parser = new PapyrusParser(new CommonTokenStream(lexer)); parser.AsDynamic().KnownUserFlags = _program.FlagsFile.NativeFlagsDict; parser.script(); var compilerType = parser.ParsedObject; var nodeBinder = new NodeBinder(); var node = nodeBinder.Bind(null, _program, new ScriptText(null, source, "0"), compilerType.GetTokenStream(), compilerType.GetAst()); var scopeBinder = new ScopeBinder(); var scopeResult = scopeBinder.Bind(compilerType, node.Value); node.Diagnostics.AddRange(scopeResult.Diagnostics); var symbolBinder = new SymbolBinder(); var symbolResult = symbolBinder.Bind(node.Value); var type = new ArrayType(_program, symbolResult.Value, compilerType, elementType.Name); _arrayTypes.Add(objectIdentifier, type); } return(_arrayTypes[objectIdentifier]); } }
/// <summary> /// Read the pdb file for this module and frame /// Retrieve infomation about the function /// </summary> /// <remarks> /// When an unmanaged app like reflector loads CLR, "Function.Module.Name" /// doesn't return a valid value and so this function returns null. /// </remarks> /// <returns>SourcePosition of the function</returns> private SourcePosition GetMetaDataInfo(CorMetadataImport importer) { SourcePosition functionPos = null; //position in this function where we are try { moduleFullName = thisFrame.Function.Module.Name; moduleShortName = System.IO.Path.GetFileName(moduleFullName); } catch (ArgumentException) { moduleFullName = ""; moduleShortName = ""; return(null); } //TODO: Implement a better method to determine the symbol path than just assuming it's in the same // directory string sympath = "."; //dealing with readinf the source in the module ISymbolReader metaReader = null; ISymbolBinder1 symbolBinder = new SymbolBinder(); try { if (moduleFullName.Length > 0) { metaReader = (symbolBinder as SymbolBinder). GetReaderForFile(importer.RawCOMObject, moduleFullName, sympath); } } catch (COMException) { //Debug.WriteLine(ed.ToString(CultureInfo.CurrentCulture.NumberFormat)); //will get here for any function which we cant read the .pdb file for //its not a big deal we just wont have source and line info } if (metaReader != null) { ISymbolMethod symMethod = null; try { symMethod = metaReader.GetMethod(new SymbolToken((int)thisFrame.Function.Token), thisFrame.Function.Version); int sequenceCount = symMethod.SequencePointCount; symDocs = new ISymbolDocument[sequenceCount]; offsets = new int[sequenceCount]; startLines = new int[sequenceCount]; startColumns = new int[sequenceCount]; endLines = new int[sequenceCount]; endColumns = new int[sequenceCount]; //Get the sequence points and store them in the apporpriate arrays. Seqeunce points //represent the different points in the files which correlate to il instruction and lines symMethod.GetSequencePoints(offsets, symDocs, startLines, startColumns, endLines, endColumns); functionPos = GetSourcePositionFromFrame(); } catch (COMException) { functionPos = null; } finally { symDocs = null; symMethod = null; } } CorType ctype = GetClassType(); if (ctype != null) { StringBuilder sb = new StringBuilder(); GetFunctionClassPath(sb, ctype); functionFullName = sb.ToString(); } else { functionFullName = ""; } MethodInfo methIn = importer.GetMethodInfo(thisFrame.Function.Token); functionFullName += "." + methIn.Name; functionShortName = methIn.Name; return(functionPos); }
public ScriptFile(ObjectIdentifier id, string filePath, PapyrusProgram program, IScriptTextProvider textProvider, ILogger <ScriptFile> logger) { _id = id; _filePath = filePath; _program = program; _textProvider = textProvider; _logger = logger; var initialVersion = _textProvider.GetTextVersion(_filePath).WaitForResult(); _scriptText = new TokenEqualityCachedValue <ScriptText, string>( () => _textProvider.GetText(_filePath).WaitForResult(), (_) => { var currentVersion = _scriptText.CurrentToken; var version = _textProvider.GetTextVersion(_filePath).WaitForResult(); if (currentVersion != version) { _logger.LogTrace($"{_id} file version changed from '{currentVersion}' to '{version}'. (Thread: {Thread.CurrentThread.ManagedThreadId})"); } return(version); }, initialVersion); _textProvider.OnScriptTextChanged += HandleScriptTextChanged; _compiler = new TokenEqualityCachedValue <ScriptCompiler, string>(() => { var compiler = new ScriptCompiler(this, _logger); compiler.CompilerNotifyHandler += (s, e) => { _logger.LogTrace($"Compiler: {e.sMessage}"); }; return(compiler); }, (_) => _scriptText.Value.Version, initialVersion); _compilationResult = new TokenEqualityCachedValue <DiagnosticResult <CompilationResult>, ScriptCompiler>(() => { DiagnosticResult <CompilationResult> compileFunc() { return(DiagnosticResult <CompilationResult> .TryWithDiagnostics((diagnostics) => { return UseCompiler((compiler, types) => { var compilationResult = new CompilationResult(); _logger.LogTrace($"Compiling {_id}... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var type = compiler.Load(types); compilationResult.CompilerType = type; compilationResult.CompilerNode = type?.GetAst(); _logger.LogTrace($"Type checking {_id}... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var typeWalker = new TypeWalker(this, type, _logger); typeWalker.OnError((s, e) => { if (!e.ErrorText.StartsWith("mismatched tree node")) { diagnostics.Add(e.ToDiagnostic()); } }); try { #if FALLOUT4 typeWalker.script(type, compiler, types); #elif SKYRIM lock (types) { if (types.ContainsKey("int")) { types.Remove("int"); types.Remove("float"); types.Remove("string"); types.Remove("bool"); } } typeWalker.script(type, compiler, types, new Stack <string>()); #endif } catch (Exception e) { _logger.LogWarning(e, $"Thrown during type checking of {_id}"); } return compilationResult; }, (s, e) => { diagnostics.Add(e.ToDiagnostic()); }); })); } // If there are diagnostic errors, we re-run the compile once in case anything was missing, // but couldn't be resolved at the time. var result = compileFunc(); if (result.Diagnostics.Count > 0) { return(compileFunc()); } return(result); }, (_) => _compiler.Value); _node = new TokenEqualityCachedValue <DiagnosticResult <ScriptNode>, CompilationResult>(() => { if (CompilerType == null) { return(null); } _logger.LogTrace($"Transforming {_id} syntax tree... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var nodeBinder = new NodeBinder(); var node = nodeBinder.Bind(this, _program, Text, CompilerType.GetTokenStream(), CompilerNode); _logger.LogTrace($"Binding script scopes to {_id} syntax tree... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var scopeBinder = new ScopeBinder(); var scopeResult = scopeBinder.Bind(CompilerType, node.Value); node.Diagnostics.AddRange(scopeResult.Diagnostics); _logger.LogTrace($"Binding {_id} symbols... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var symbolBinder = new SymbolBinder(); var symbolResult = symbolBinder.Bind(node.Value); node.Diagnostics.AddRange(symbolResult.Diagnostics); return(node); }, (_) => _compilationResult.Value?.Value); _type = new TokenEqualityCachedValue <ScriptType, ScriptSymbol>(() => { if (Symbol == null) { return(null); } _logger.LogTrace($"Creating {_id} type... (Thread: {Thread.CurrentThread.ManagedThreadId})"); return(new ScriptType(Program, Symbol, CompilerType)); }, (_) => Symbol); }