예제 #1
0
        } // end _TryLoadAssembly()

        public static void LoadPlugin(string path, IPipelineCallback pipeline)
        {
            _EnsureInitialized();

            pipeline.WriteVerbose("Looking for plugin types in: {0}", path);
            Assembly asm = _TryLoadAssembly(path, pipeline);

            if (null == asm)
            {
                return; // already wrote an error
            }
            Type dtdPluginInterface = typeof(IDbgDerivedTypeDetectionPlugin);

            foreach (var candidateType in asm.GetExportedTypes())
            {
                if (dtdPluginInterface.IsAssignableFrom(candidateType))
                {
                    pipeline.WriteVerbose("Found Derived Type Detection plugin type: {0}", candidateType.FullName);
                    var constructor = candidateType.GetConstructor(Type.EmptyTypes);
                    if (null == constructor)
                    {
                        DbgProviderException dpe = new DbgProviderException(Util.Sprintf("The plugin type '{0}' from '{1}' cannot be used because it has no public, parameterless constructor.",
                                                                                         candidateType.FullName,
                                                                                         path),
                                                                            "PluginTypeMissingDefaultConstructor",
                                                                            System.Management.Automation.ErrorCategory.InvalidData,
                                                                            candidateType);
                        try { throw dpe; } catch (Exception) { }  // give it a stack
                        pipeline.WriteError(dpe);
                    }

                    try
                    {
                        var plugin = (IDbgDerivedTypeDetectionPlugin)constructor.Invoke(null);
                        sm_dtdPlugins.Add(plugin);
                        pipeline.WriteVerbose("Registered Derived Type Detection plugin: {0}", plugin.Name);
                    }
                    catch (Exception e)  // I hate this.
                    {
                        DbgProviderException dpe = new DbgProviderException(Util.Sprintf("The plugin type '{0}' from '{1}' cannot be used because its constructor threw an exception: {2}",
                                                                                         candidateType.FullName,
                                                                                         path,
                                                                                         Util.GetExceptionMessages(e)),
                                                                            "PluginTypeConstructorThrew",
                                                                            System.Management.Automation.ErrorCategory.OpenError,
                                                                            e,
                                                                            candidateType);
                        try { throw dpe; } catch (Exception) { }  // give it a stack
                        pipeline.WriteError(dpe);
                    }
                } // end if( it's a DTD plugin type )
            }     // end foreach( candidateType )
        }         // end LoadPlugin()
예제 #2
0
        } // end TryFindPossibleOffsetFromDerivedClass()

        private static Assembly _TryLoadAssembly(string path, IPipelineCallback pipeline)
        {
            Exception e = null;

            try
            {
                return(Assembly.LoadFrom(path));
            }
            catch (BadImageFormatException bife) { e = bife; }
            catch (System.IO.IOException ioe) { e = ioe; }
            catch (System.Security.SecurityException se) { e = se; }

            var dpe = new DbgProviderException(Util.Sprintf("Could not load {0}: {1}",
                                                            System.IO.Path.GetFileName(path),
                                                            Util.GetExceptionMessages(e)),
                                               "PluginLoadFailed",
                                               System.Management.Automation.ErrorCategory.OpenError,
                                               e,
                                               path);

            try { throw dpe; } catch (Exception) { }  // give it a stack
            pipeline.WriteError(dpe);
            return(null);
        } // end _TryLoadAssembly()
예제 #3
0
            } // end constructor

            public void AddLine(string s)
            {
                switch (m_state)
                {
                case WfdState.ExpectingBlockId:
                    if ((s.Length > 0) && (s[s.Length - 1] != ':'))
                    {
                        // It's not a block ID... this can happen when "Flow
                        // analysis was incomplete".
                        m_currentBlockId = new ColorString(ConsoleColor.DarkGray, "<unknown>").MakeReadOnly();
                        m_pipeline.WriteObject(_ParseDisassembly(0,       // will get parsed out of s
                                                                 s,
                                                                 m_currentBlockId,
                                                                 m_hasCodeBytes));
                    }
                    else
                    {
                        m_currentBlockId = DbgProvider.ColorizeSymbol(s).MakeReadOnly();
                    }
                    m_state = WfdState.ExpectingInstructionOrBlankLine;
                    break;

                case WfdState.ExpectingInstructionOrBlankLine:
                    if (String.IsNullOrEmpty(s))
                    {
                        m_state          = WfdState.ExpectingBlockId;
                        m_currentBlockId = null;
                    }
                    else
                    {
                        m_pipeline.WriteObject(_ParseDisassembly(0,       // will get parsed out of s
                                                                 s,
                                                                 m_currentBlockId,
                                                                 m_hasCodeBytes));
                    }
                    break;

                // This is a horrible state. But sometimes we see it, like
                // sometimes after a flow analysis error.
                case WfdState.DontKnow:
                    if (s.StartsWith("Flow analysis", StringComparison.OrdinalIgnoreCase))
                    {
                        //m_flowAnalysisWarning = true;
                        m_pipeline.WriteWarning(s);
                        m_state = WfdState.DontKnow;
                        break;
                    }
                    else if (s.StartsWith("*** WARNING: ", StringComparison.OrdinalIgnoreCase))
                    {
                        m_pipeline.WriteWarning(s.Substring(13));         // trim off what will become redundant "WARNING" label.
                        m_state = WfdState.DontKnow;
                        break;
                    }
                    else if (s.StartsWith("*** ERROR: ", StringComparison.OrdinalIgnoreCase))
                    {
                        s = s.Substring(11);       // trim off what will become redundant "ERROR" label.
                        var dpe = new DbgProviderException(s,
                                                           "ErrorDuringUnassemble",
                                                           ErrorCategory.ReadError);
                        try { throw dpe; } catch (Exception) { }      // give it a stack.
                        m_pipeline.WriteError(dpe);
                        m_state = WfdState.DontKnow;
                        break;
                    }
                    else if (s.StartsWith("No code found, aborting", StringComparison.OrdinalIgnoreCase))
                    {
                        var dpe = new DbgProviderException(s,
                                                           "NoCodeFound",
                                                           ErrorCategory.ReadError);
                        try { throw dpe; } catch (Exception) { } // give it a stack.
                        m_pipeline.WriteError(dpe);
                        m_state = WfdState.DontKnow;             // actually, we should be done now.
                        break;
                    }
                    else if ((s.Length > 0) && (s[s.Length - 1] == ':'))
                    {
                        // Looks like a block ID...
                        m_state = WfdState.ExpectingBlockId;
                        AddLine(s);
                    }
                    else if (String.IsNullOrEmpty(s))
                    {
                        m_state          = WfdState.ExpectingBlockId;
                        m_currentBlockId = null;
                    }
                    else
                    {
                        m_state = WfdState.ExpectingInstructionOrBlankLine;
                        AddLine(s);
                    }
                    break;

                default:
                    Util.Fail("Invalid parse state.");
                    throw new Exception("Invalid parse state.");
                }
            } // end AddLine()
예제 #4
0
        } // end AddSourceFile()

        /// <summary>
        ///    Re-runs the list of registered source files, after clearing the internal
        ///    list of registered source files.
        /// </summary>
        /// <remarks>
        ///    It is assumed that when a script runs, it calls some command that causes
        ///    AddSourceFile to be called, thereby re-registering itself. If a script
        ///    produces an error, however, it is kept in the list of source files, so that
        ///    a user can fix the error and call this again without re-registering the
        ///    script.
        ///
        ///    If a script in appendScripts is already in the list, no change is made (the
        ///    script does not get added again to the end of the list, or moved). If a
        ///    script in prependScripts is already in the list, it gets moved from its
        ///    original position to the front.
        /// </remarks>
        public void Reload(CommandInvocationIntrinsics invokeCommand,
                           IList <string> appendScripts,
                           IList <string> prependScripts,
                           string dataDisplayName,  // for verbose messages
                           IPipelineCallback pipe)
        {
            if (null == pipe)
            {
                throw new ArgumentNullException("pipe");
            }

            pipe.WriteVerbose("Dumping old {0}...", dataDisplayName);
            m_DumpContent();

            if (null != appendScripts)
            {
                foreach (var newScript in appendScripts)
                {
                    // Unlike the prepend case, here we don't change the position of the
                    // script in the list if it's already in it.
                    if ((null != newScript) && m_sourceFilesSet.Add(newScript))
                    {
                        pipe.WriteVerbose("Appending script: {0}", newScript);
                        m_sourceFiles.AddLast(newScript);
                    }
                }
            }

            if (null != prependScripts)
            {
                foreach (var newScript in prependScripts)
                {
                    if (null != newScript)
                    {
                        if (m_sourceFilesSet.Remove(newScript))
                        {
                            pipe.WriteVerbose("Prepending (moving) script: {0}", newScript);
                            m_sourceFiles.Remove(newScript);
                        }
                        else
                        {
                            pipe.WriteVerbose("Prepending script: {0}", newScript);
                        }

                        m_sourceFiles.AddFirst(newScript);
                    }
                }
            }

            // It's possible that there's conditional logic in the scripts that causes
            // different scripts to run, so we'd better clear out the existing source
            // files list (after making a copy).
            var oldSourceFiles = m_sourceFiles.ToArray();

            m_sourceFiles.Clear();
            m_sourceFilesSet.Clear();
            foreach (string sourceScript in oldSourceFiles)
            {
                try
                {
                    // If there are errors parsing the file, then it won't be run, and if
                    // it doesn't get run, something won't call AddSourceFile, and if it
                    // doesn't call AddSourceFile, we won't save the script file to run
                    // again next time someone calls Reload. So we'll save the script name
                    // in the "files to run" /now/, instead of later.
                    pipe.WriteVerbose("Adding {0} from: {1}", dataDisplayName, sourceScript);
                    if (AddSourceFile(sourceScript))
                    {
                        ScriptBlockAst ast = InvokeScriptCommand.LoadScript(sourceScript);
                        // TODO: should I do anything with any output?
                        InvokeScriptCommand.InvokeScript(invokeCommand, ast.GetScriptBlock(), true);
                    }
                    else
                    {
                        // I don't think it should be possible to get here.
                        Util.Fail("How did we get here?");
                    }
                }
                catch (DbgProviderException dpe)
                {
                    pipe.WriteError(dpe.ErrorRecord);
                }
                catch (RuntimeException re)
                {
                    pipe.WriteError(re.ErrorRecord);
                }
            }
        } // end Reload()