Пример #1
0
        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;
        }
Пример #2
0
        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);
        }
Пример #3
0
        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]);
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        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);
        }