Пример #1
0
        public static BoolEvaluation TestUClassFlags(string uclass_expr_str, string flags, DkmVisualizedExpression context_expr)
        {
            ExpressionManipulator em = ExpressionManipulator.FromExpression(uclass_expr_str);

            em = em.PtrCast(Typ.UClass).PtrMember(Memb.ClassFlags);
            var class_flags_expr_str = em.Expression;

            // @TODO: Could do the flag test on this side by hard coding in the value of RF_Native, but for now
            // doing it the more robust way, and evaluating the expression in the context of the debugee.
            return(TestExpressionFlags(class_flags_expr_str, flags, context_expr));
        }
Пример #2
0
        // Given an expression which resolves to a pointer of any kind, returns the pointer value as an integer.
        public static ulong EvaluatePointerAddress(string pointer_expr_str, DkmVisualizedExpression context_expr)
        {
            ExpressionManipulator em = ExpressionManipulator.FromExpression(pointer_expr_str);
            // Cast to void* to avoid unnecessary visualization processing.
            string address_expr_str = em.PtrCast(Cpp.Void).Expression;
            var    address_eval     = (DkmEvaluationResult)DefaultEE.DefaultEval(address_expr_str, context_expr, true);

            if (address_eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
            {
                var eval = address_eval as DkmSuccessEvaluationResult;
                return(eval.Address != null ? eval.Address.Value : 0);
            }
            return(0);
        }
Пример #3
0
        // Flags should be in a form that can be inserted into a bit test expression in the
        // debuggee context (eg. a raw integer, or a combination of RF_*** flags)
        public static bool TestUObjectFlags(string uobj_expr_str, string flags, DkmVisualizedExpression context_expr)
        {
            ExpressionManipulator em = ExpressionManipulator.FromExpression(uobj_expr_str);

            em = em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjFlags);
            var obj_flags_expr_str = em.Expression;

            // @NOTE: Value string is formatted as 'RF_... | RF_... (<integer value>)'
            // So for now, rather than extracting what we want, just inject the full expression for
            // the flags member into the below flag test expression.
            //string obj_flags_str = ((DkmSuccessEvaluationResult)obj_flags_expr.EvaluationResult).Value;

            // @TODO: Could do the flag test on this side by hard coding in the value of RF_Native, but for now
            // doing it the more robust way, and evaluating the expression in the context of the debugee.
            string flag_test_expr_str = String.Format(
                "({0} & {1}) != 0",
                obj_flags_expr_str,
                flags
                );

            return(EvaluateBooleanExpression(flag_test_expr_str, context_expr));
        }
        public bool DetermineObjectCanHaveProperties()
        {
            switch (Config.PropertyDisplayPolicy)
            {
            case Config.PropDisplayPolicyType.BlueprintOnly:
            {
                // See if the actual class of the object instance is native or not.
                var uclass_em     = obj_em_.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass);
                var is_native_res = UE4Utility.TestUClassFlags(
                    uclass_em.Expression,
                    ClassFlags.Native,
                    context_expr_
                    );
                return(is_native_res.IsValid && !is_native_res.Value);
            }

            case Config.PropDisplayPolicyType.All:
                return(true);

            default:
                return(false);
            }
        }
Пример #5
0
        public void EvaluateProperties()
        {
            List <DkmEvaluationResult> evals = new List <DkmEvaluationResult>();

            // Assume we've been constructed with the fabricated property list expression
            DkmChildVisualizedExpression proplist_expr = (DkmChildVisualizedExpression)expression_;

            Debug.Assert(proplist_expr != null);

            // start could be an expression with the type of any UObject-derived class
            DkmVisualizedExpression start_expr = proplist_expr.Parent;

            string base_expression_str = Utility.GetExpressionFullName(start_expr);

            base_expression_str = Utility.StripExpressionFormatting(base_expression_str);

            ExpressionManipulator obj_em = null;

            // @TODO: Deal with non-pointer start expression
            obj_em = ExpressionManipulator.FromExpression(base_expression_str);

            // Determine if our base expression is <UObject-type>* or <UObject-type>
            bool is_pointer = start_expr.GetDataItem <UObjectDataItem>().IsPointer;

            if (!is_pointer)
            {
                obj_em = obj_em.AddressOf();
            }

            var uclass_em = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass);

            if (Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly)
            {
                // See if the actual class of the object instance whose properties we want to enumerate
                // is native or not.
                var is_native_res = UE4Utility.TestUClassFlags(
                    uclass_em.Expression,
                    ClassFlags.Native,
                    start_expr
                    );

                // If the instance class is native, then it can't possibly have any non-native properties,
                // so bail out now.
                // @TODO: Even if the class is not native, we should still be able to avoid doing all the work
                // for enumerating every native property in order to find the non-native ones...
                // @TODO: How best to deal with failed is_native evaluation?
                if (is_native_res.IsValid && is_native_res.Value)
                {
                    return;
                }
            }

            // Get the UStruct part of the UClass, in order to begin iterating properties
            var ustruct_em = uclass_em.PtrCast(Typ.UStruct);
            // Now access PropertyLink member, which is the start of the linked list of properties
            var prop_em = ustruct_em.PtrMember(Memb.FirstProperty);

            uint idx = 0;

            while (true)
            {
                Debug.Print("UE4PV: Invoking raw eval on UProperty* expression");

                var prop_eval = DefaultEE.DefaultEval(prop_em.Expression, start_expr, true) as DkmSuccessEvaluationResult;
                Debug.Assert(prop_eval != null);

                if (prop_eval.Address.Value == 0)
                {
                    // nullptr, end of property list
                    break;
                }

                bool should_skip = false;

                if (!should_skip && Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly)
                {
                    // Check to see if this property is native or blueprint
                    // We can test this by getting the UProperty's Outer, and checking its object flags for RF_Native.
                    var prop_outer_em = prop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjOuter);

                    // @NOTE: RF_Native has gone, and checking for RF_MarkAsNative never seems to return true...
                    //var is_native_res = UE4Utility.TestUObjectFlags(prop_outer_em.Expression, ObjFlags.Native, start_expr);

                    // So, access class flags instead.
                    // Note that we make the assumption here that the property's outer is a UClass, which should be safe since
                    // we're starting out with a uobject, so all properties, including inherited ones, should be outered to a uclass.
                    var prop_outer_uclass_em = prop_outer_em.PtrCast(Typ.UClass);
                    var is_native_res        = UE4Utility.TestUClassFlags(prop_outer_uclass_em.Expression, ClassFlags.Native, start_expr);

                    // According to UE4 UStruct API docs, property linked list is ordered from most-derived
                    // to base. If so, we should be able to bail out here knowing that having hit a native property,
                    // all following properties must be native too.
                    if (is_native_res.IsValid && is_native_res.Value)
                    {
                        return;
                    }
                }

                if (!should_skip)
                {
                    // @TODO: Here we use the starting expression for the container.
                    // May not work if the root expression was not of pointer type!!
                    var prop_val_eval = GeneratePropertyValueEval(
                        obj_em.Expression,
                        prop_em.Expression,
                        idx,
                        start_expr
                        );
                    if (prop_val_eval != null && !Config.IsPropertyHidden(prop_val_eval.Name))
                    {
                        prop_evals_[prop_val_eval.Name] = prop_val_eval;
                        ++idx;
                    }
                }

                // Advance to next link
                prop_em = prop_em.PtrMember(Memb.NextProperty);
            }
        }