示例#1
0
        protected IDisposable SetDebuggerAndContextAndUpdateCallbacks(string contextPath)
        {
            if (String.IsNullOrEmpty(contextPath))
            {
                PathInfo pi = this.CurrentProviderLocation(DbgProvider.ProviderId);
                contextPath = pi.ProviderPath;
            }
            else
            {
                contextPath = GetUnresolvedProviderPathFromPSPath(contextPath);
            }

            Debugger = DbgProvider.GetDebugger(contextPath);

            if ((null == Debugger) || Debugger.NoTarget)
            {
                throw new DbgProviderException("No target.",
                                               "NoTarget",
                                               ErrorCategory.InvalidOperation);
            }

            var inputCallbacks = Debugger.GetInputCallbacks() as DebugInputCallbacks;

            if (null != inputCallbacks)
            {
                inputCallbacks.UpdateCmdlet(this);
            }

            var disposable = Debugger.SetCurrentCmdlet(this);

            Debugger.SetContextByPath(contextPath);

            return(disposable);
        } // end SetDebuggerAndContextAndUpdateCallbacks()
示例#2
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            //   WriteObject( "\u009b91mThis should be red.\u009bm This should not.\r\n" );
            //   WriteObject( "\u009b91;41mThis should be red on red.\u009bm This should not.\r\n" );
            //   WriteObject( "\u009b91;100mThis should be red on gray.\u009b" );
            //   WriteObject( "m This should not.\r\n" );

            //   WriteObject( "\u009b" );
            //   WriteObject( "9" );
            //   WriteObject( "1;10" );
            //   WriteObject( "6mThis should be red on cyan.\u009b" );
            //   WriteObject( "m This should \u009bm\u009bmnot.\r\n" );


            // //WriteObject( "\u009b92mModLoad:\u009bm 758a0000 758ac000   \u009b97mCRYPTBASE\u009bm\r\n" );
            // //WriteObject( "\u009b92mModLoad:\u009bm 758a0000 758ac000   \u009b30;107mCRYPTBASE\u009bm\r\n" );


            PathInfo pi       = this.CurrentProviderLocation(DbgProvider.ProviderId);
            var      debugger = DbgProvider.GetDebugger(pi.ProviderPath);

            debugger.SetContextByPath(pi.ProviderPath);
        } // end ProcessRecord()
示例#3
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            PathInfo pi       = this.CurrentProviderLocation(DbgProvider.ProviderId);
            var      debugger = DbgProvider.GetDebugger(pi.ProviderPath);

            debugger.SetContextByPath(pi.ProviderPath);
            WDebugSymbols ds = (WDebugSymbols)debugger.DebuggerInterface;
        } // end ProcessRecord()
        public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
        {
            object originalInputData = inputData;

            var pso = inputData as PSObject;

            if (null != pso)
            {
                inputData = pso.BaseObject;
            }

            if (inputData is DbgTypeInfo)
            {
                return(inputData);
            }

            string path     = engineIntrinsics.SessionState.Path.CurrentProviderLocation(DbgProvider.ProviderId).ProviderPath;
            var    debugger = DbgProvider.GetDebugger(path);

            Exception e   = null;
            string    str = inputData as string;

            if (null != str)
            {
                try
                {
                    // TODO: Would be nice to ask the PowerShell team to plumb cancellation support
                    // through parameter transformation.
                    var types = debugger.GetTypeInfoByName(str,
                                                           System.Threading.CancellationToken.None).ToList();
                    if (null != types)
                    {
                        if (types.Count > 1)
                        {
                            engineIntrinsics.InvokeCommand.InvokeScript(Util.Sprintf("Write-Warning 'Multiple types found for name \"{0}\".'",
                                                                                     str));
                            LogManager.Trace("Warning: TypeTransformationAttribute: found multiple types for name '{0}'.",
                                             str);
                        }
                        else if (0 != types.Count)
                        {
                            return(types[0]);
                        }
                    }
                }
                catch (DbgProviderException dpe)
                {
                    e = dpe;
                }
            } // end if( it's a string )

            throw CreateRecoverableAtme(e,
                                        "Type not found. (Could not convert '{0}' to a type.)",
                                        originalInputData);
        } // end Transform()
        public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
        {
            object originalInputData = inputData;

            var pso = inputData as PSObject;

            if (null != pso)
            {
                inputData = pso.BaseObject;
            }

            if (inputData is string)
            {
                return(inputData);
            }

            if (inputData is DbgModuleInfo)
            {
                return(((DbgModuleInfo)inputData).ImageName);
            }

            string path     = engineIntrinsics.SessionState.Path.CurrentProviderLocation(DbgProvider.ProviderId).ProviderPath;
            var    debugger = DbgProvider.GetDebugger(path);

            Exception e = null;

            // Maybe it is an address?
            try
            {
                object addrObj = AddressTransformationAttribute.Transform(
                    engineIntrinsics,
                    null,
                    true,                  // skipGlobalSymbolTest
                    false,                 // throwOnFailure
                    originalInputData);
                if (null != addrObj)
                {
                    var mod = new DbgModuleInfo(debugger,
                                                (ulong)addrObj,
                                                debugger.GetCurrentTarget());
                    return(mod.Name);
                }
            }
            catch (DbgEngException dee)
            {
                e = dee;
            }

            throw CreateRecoverableAtme(e,
                                        "Could not convert '{0}' to a module name.",
                                        originalInputData);
        } // end Transform()
        } // end _TryConvertToUint()

        public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
        {
            object originalInputData = inputData;

            var pso = inputData as PSObject;

            if (null != pso)
            {
                inputData = pso.BaseObject;
            }

            if (inputData is DbgUModeThreadInfo)
            {
                return(inputData);
            }

            if (null == inputData)
            {
                // Some commands CAN take a thread, but don't require it.
                return(null);
            }

            var type = inputData.GetType();

            if (type.IsArray)
            {
                Array asArray = (Array)inputData;
                DbgUModeThreadInfo[] threads = new DbgUModeThreadInfo[asArray.Length];
                for (int i = 0; i < threads.Length; i++)
                {
                    threads[i] = Transform(engineIntrinsics, asArray.GetValue(i)) as DbgUModeThreadInfo;
                    if (null == threads[i])
                    {
                        // Array embedded within an array? Not going to handle that.
                        throw new ArgumentTransformationMetadataException(Util.Sprintf("Could not convert item at index {0} to a thread.",
                                                                                       i));
                    }
                }
                return(threads);
            } // end if( array )

            DbgUModeThreadInfo thread = null;
            uint tid;

            if (_TryConvertToUint(engineIntrinsics, originalInputData, out tid))
            {
                string path     = engineIntrinsics.SessionState.Path.CurrentProviderLocation(DbgProvider.ProviderId).ProviderPath;
                var    debugger = DbgProvider.GetDebugger(path);

                try
                {
                    thread = debugger.GetUModeThreadByDebuggerId(tid);
                    return(thread);
                }
                catch (DbgProviderException)
                {
                    // ignore
                }

                // Maybe it's a system tid?
                // I wonder if this "helpfulness" actually confuses things...
                try
                {
                    thread = debugger.GetThreadBySystemTid(tid);
                    return(thread);
                }
                catch (DbgProviderException)
                {
                    // ignore
                }

                throw new ArgumentTransformationMetadataException(Util.Sprintf("No such thread: {0}.",
                                                                               tid));
            }

            throw CreateRecoverableAtme("Could not convert '{0}' to a thread.",
                                        originalInputData);
        } // end Transform()
        public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
        {
            object originalInputData = inputData;

            var pso = inputData as PSObject;

            if (null != pso)
            {
                inputData = pso.BaseObject;
            }

            if (inputData is DbgModuleInfo)
            {
                return(inputData);
            }

            if (null == inputData)
            {
                return(null);
            }

            string path     = engineIntrinsics.SessionState.Path.CurrentProviderLocation(DbgProvider.ProviderId).ProviderPath;
            var    debugger = DbgProvider.GetDebugger(path);

            Exception e   = null;
            string    str = inputData as string;

            if (null != str)
            {
                if (0 == str.Length)
                {
                    return(null);
                }

                try
                {
                    var foundMod = debugger.Modules.FirstOrDefault((m) => 0 == Util.Strcmp_OI(m.Name, str));
                    if (null != foundMod)
                    {
                        return(foundMod);
                    }
                }
                catch (DbgProviderException dpe)
                {
                    e = dpe;
                }
            }

            if (null == e)
            {
                // Maybe it was an address...
                try
                {
                    object addrObj = AddressTransformationAttribute.Transform(
                        engineIntrinsics,
                        null,
                        true,                  // skipGlobalSymbolTest
                        false,                 // throwOnFailure
                        originalInputData);
                    if (null != addrObj)
                    {
                        return(new DbgModuleInfo(debugger,
                                                 (ulong)addrObj,
                                                 debugger.GetCurrentTarget()));
                    }
                }
                catch (DbgEngException dee)
                {
                    e = dee;
                }
            }

            throw CreateRecoverableAtme(e,
                                        "Could not convert '{0}' to a module.",
                                        originalInputData);
        } // end Transform()
        // You must pass either the engineIntrinsics, or the path. (You don't need both.)
        // This is a hacky-wacky workaround for the fact that there's no way for user code
        // to get an EngineIntrinsics object, but I want user code to be able to call this
        // method directly, and I don't want everyone to /always/ have to get the path.
        public static object Transform(EngineIntrinsics engineIntrinsics,
                                       string dbgProviderPath,
                                       bool skipGlobalSymbolTest,
                                       bool throwOnFailure,
                                       bool dbgMemoryPassthru,
                                       bool allowList,
                                       object inputData)
        {
            //Console.WriteLine( "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" );
            //Console.WriteLine( "{0} 1: inputData type: {1}", DebuggingTag, inputData.GetType().FullName );
            //Console.WriteLine( "{0} 2: dynamic type: {1}", DebuggingTag, ((dynamic) inputData).GetType().FullName );
            //Console.WriteLine( "{0} 3: ToString(): {1}", DebuggingTag, inputData.ToString() );
            //Console.WriteLine( "{0} 4: dynamic ToString(): {1}", DebuggingTag, ((dynamic) inputData).ToString() );

            var pso = inputData as PSObject;

            if (allowList)
            {
                var objList = inputData as IList;

                if ((null != pso) && (pso.BaseObject is IList))
                {
                    objList = (IList)pso.BaseObject;
                }

                if (null != objList)
                {
                    ulong[] addrs = new ulong[objList.Count];
                    try
                    {
                        for (int i = 0; i < objList.Count; i++)
                        {
                            addrs[i] = (ulong)Transform(engineIntrinsics,
                                                        dbgProviderPath,
                                                        skipGlobalSymbolTest,
                                                        true,     // throwOnFailure,
                                                        dbgMemoryPassthru,
                                                        false,    // we don't allow nested arrays
                                                        objList[i]);
                        } // end for( each obj )
                        return(addrs);
                    }
                    catch (Exception e_temp)
                    {
                        if (throwOnFailure ||
                            (!(e_temp is DbgProviderException) && !(e_temp is MetadataException)))
                        {
                            throw;
                        }
                    }
                } // end if( it's an array )
            }     // end if( allowList )

            if (null != pso)
            {
                // Addresses are always expressed in hexadecimal.
                //
                // Thus you can type a leading "0x", but it is redundant and not
                // necessary.
                //
                // If the address contains a backtick, or for some reason is expressed in
                // decimal with a leading "0n", or has hex-only digits ([a-f]) but no
                // leading "0x", then PowerShell will parse it as a string. Then we can
                // handle parsing it ourselves (in this method).
                //
                // However... if the user /did/ use a leading "0x" and there is no
                // backtick, OR if the address contains no hex-only digits and there is no
                // backtick, OR if the address ended with "eN" (where N is a digit)...
                // then PowerShell will have parsed it as a number (giving us either an
                // UInt32, or a UInt64, or a double, depending on how big).
                //
                // In that case, we need to figure out whether or not the user typed an
                // "0x", because if they did not, that means that PowerShell parsed it
                // incorrectly (as a base-10 number, and possibly using scientific
                // notation, instead of a base-16 number).
                //
                // Fortunately, if we have the PSObject for that typed number, we can get
                // the originally typed string, which will let us know if there was an
                // "0x" or not.
                //
                // Update: "if we have the PSObject for that typed number, we can get the
                // originally typed string": unfortunately, that is not always true, such
                // as when the address is piped in. TODO: can we change PowerShell to
                // allow us to get the string as originally typed in more cases?

                //Console.WriteLine( "{0} 5: BaseObject type: {1}", DebuggingTag, pso.BaseObject.GetType().FullName );
                if ((pso.BaseObject is int) ||
                    (pso.BaseObject is long) ||
                    (pso.BaseObject is double) ||
                    (pso.BaseObject is float))
                {
                    // The standard way to get the originally typed string is to use
                    // LanguagePrimitives.ConvertTo< string >. However, it seems that it
                    // wants to /always/ give us a string back, even if it doesn't have
                    // the originally typed string. So if we use that method, we don't
                    // know if the string we get back actually is what was originally
                    // typed or not.
                    //var asTyped = LanguagePrimitives.ConvertTo< string >( pso );

                    // This /will/ get what the user actually typed (if it was typed),
                    // but relies on reflection to get at PS internals. :(
                    var asTyped = _GetAsTyped_usingIckyPrivateReflection(pso);
                    //Console.WriteLine( "As typed: {0}", asTyped );

                    if (null != asTyped)
                    {
                        if (asTyped.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                        {
                            // Yes, they typed an "0x", so PS correctly parsed as hex.
                            //
                            // The cast to (int) first is to un-box. Then to (uint) to
                            // prevent sign extension.
                            if (pso.BaseObject is int)
                            {
                                return((ulong)(uint)(int)pso.BaseObject);
                            }

                            if (pso.BaseObject is long)
                            {
                                return(unchecked ((ulong)(long)pso.BaseObject));
                            }

                            // Should not reach here.
                            Util.Fail("How could the typed string start with 0x but get parsed as something besides an int or long?");
                        }

                        inputData = asTyped; // we'll re-parse it below as base-16
                    }
                    else
                    {
                        // If we get here, then it /was/ typed, but piped in:
                        //
                        //    01234000 | ConvertTo-Number
                        //  0x01234000 | ConvertTo-Number
                        //
                        // So PS parsed it... but if we ended up with an integer type, we
                        // don't know if it parsed as decimal or hex, so we can't be sure
                        // how to undo that parsing. :(  For now we'll have to just assume
                        // that the user knows that they need to use 0x when piping in.
                        //
                        // That sounds bad, because actually a user probably will /not/
                        // know that, but the alternative is worse; a user who directly
                        // specifies hex ("0x01230000 | something") should never get the
                        // wrong result.
                        //
                        // TODO: see if we can get PS to preserve the as-typed value for
                        // things that are piped in.
                        inputData = pso.BaseObject;
                    }
                }
                else
                {
                    inputData = pso.BaseObject;
                }
            }
            //Console.WriteLine( "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" );

            if (dbgMemoryPassthru && (inputData is DbgMemory))
            {
                return(inputData);
            }

            // Some commands do not require an address.
            if (null == inputData)
            {
                return((ulong)0);
            }

            if (inputData is ulong)
            {
                return(inputData);
            }

            // We used to assume that this was probably a base-16 number without any
            // letters in it, so PS interpreted it as a base-10 number, so then we would
            // undo that. And hope it was right. But unfortunately, that messed up the
            // scenario where you assign a number to a variable ("$blah = 123"), so I'm
            // going the other way now--we'll assume it's already correct. Unfortunately,
            // that means that on 32-bit, you'll need to always use "0x" to be safe. :(
            // if( (inputData is int) || (inputData is long) )
            // {
            //     inputData = inputData.ToString();
            // }

            if (inputData is int)
            {
                return((ulong)(uint)(int)inputData);   // 1st cast unboxes; 2nd prevents sign extension
            }
            if (inputData is long)
            {
                return((ulong)(long)inputData);  // need two casts in order to unbox first.
            }
            if (inputData is uint)
            {
                // This can happen, for instance, when using the register variables for a
                // 32-bit process ("u $eip").
                return((ulong)(uint)inputData);  // need two casts in order to unbox first.
            }

            if (inputData is byte)
            {
                // This can happen because we [ab]use AddressTransformationAttribute to
                // convert lots of numeric data, not just addresses. (For instance, the
                // "eb" command.)
                return((ulong)(byte)inputData);  // need two casts in order to unbox first.
            }

            if (inputData is double)
            {
                // This can happen when doing arithmetic. For instance, this will yield
                // Double:
                //
                //    [UInt32] $ui1 = 0x03
                //    [UInt32] $ui2 = 0x01
                //    ($ui2 - $ui1).GetType()
                //
                // To determine if it's really something that can be represented as a
                // ulong, we'll round-trip it through a ulong back to a double, and then
                // see if the bits representation matches the original double.

                double dOrig    = (double)inputData;
                Int64  origBits = BitConverter.DoubleToInt64Bits(dOrig);
                unchecked
                {
                    ulong  asUlong = (ulong)(long)dOrig;
                    double d2      = Convert.ToDouble((long)asUlong);
                    Int64  d2Bits  = BitConverter.DoubleToInt64Bits(d2);
                    if (d2Bits == origBits)
                    {
                        // We round-tripped back to double: it doesn't have any fractional
                        // part.
                        return(asUlong);
                    }
                }
            } // end if( inputData is double )

            Exception e   = null;
            string    str = inputData as string;

            if (null != str)
            {
                // Some commands do not require an address.
                if (0 == str.Length)
                {
                    return((ulong)0);
                }

                if ((1 == str.Length) && (str[0] == '.'))
                {
                    dbgProviderPath = _GetDbgProviderPath(dbgProviderPath, engineIntrinsics);
                    var regSet = DbgProvider.GetRegisterSetForPath(dbgProviderPath);
                    return(regSet.Pseudo["$ip"].Value);
                }

                ulong address;
                if (DbgProvider.TryParseHexOrDecimalNumber(str, out address))
                {
                    return(address);
                }

                // Mabye it's a symbolic name?
                if (!skipGlobalSymbolTest)
                {
                    dbgProviderPath = _GetDbgProviderPath(dbgProviderPath, engineIntrinsics);
                    var debugger = DbgProvider.GetDebugger(dbgProviderPath);
                    try
                    {
                        address = debugger.GetOffsetByName(str);
                        return(address);
                    }
                    catch (DbgProviderException dpe)
                    {
                        e = dpe;
                    }
                }
            }

            // Check for implicit conversion to ulong. (For instance, types that derive
            // from DbgPointerValueBase have this.)
            ulong addr;

            if (_TryImplicitConversionTo(inputData, out addr))
            {
                return(addr);
            }

            if (!throwOnFailure)
            {
                return(null);
            }

            if (null != e)
            {
                ExceptionDispatchInfo.Capture(e).Throw();
            }

            // https://github.com/PowerShell/PowerShell/issues/7600
            //
            // For parameter binding to be able to continue (for example, to try binding
            // by property name), this exception needs to wrap a PSInvalidCastException.
            throw CreateRecoverableAtme("Could not convert '{0}' to an address.", inputData);
        } // end Transform()