示例#1
0
        protected bool MethodCallback(SPEEmulator.IEndianBitConverter c, uint offset)
        {
            uint sp = c.ReadUInt(offset);

            //Stack size is 77 elements, and return address is next next instruction
            uint call_address = (c.ReadUInt(sp + (16 * 77)) - 4) / 4;

            Mono.Cecil.MethodReference calledmethod;
            m_callpoints.TryGetValue((int)call_address, out calledmethod);

            if (calledmethod == null)
            {
                foreach (KeyValuePair <int, Mono.Cecil.MethodReference> f in m_callpoints)
                {
                    Console.WriteLine("Call registered at {0} for method {1}", f.Key, f.Value.DeclaringType.FullName + "::" + f.Value.Name);
                }
                throw new Exception("No method call registered at " + call_address);
            }

            //All good, we have a real function, now load all required arguments onto PPE
            object[] arguments = new object[calledmethod.Parameters.Count];

            System.Reflection.MethodInfo m = AccCIL.AccCIL.FindReflectionMethod(calledmethod);
            if (m == null)
            {
                throw new Exception("Unable to find function called: " + calledmethod.DeclaringType.FullName + "::" + calledmethod.Name);
            }

            uint   arg_base  = sp + 32;
            uint   sp_offset = arg_base;
            object @this     = null;

            SPEObjectManager manager = new SPEObjectManager(c);

            if (!m.IsStatic)
            {
                Type argtype  = m.DeclaringType;
                uint objindex = (uint)manager.ReadRegisterPrimitiveValue(typeof(uint), sp_offset);
                @this      = manager.ReadObjectFromLS(objindex);
                sp_offset += 16;
            }

            for (int i = 0; i < arguments.Length; i++)
            {
                Type argtype = Type.GetType(calledmethod.Parameters[i].ParameterType.FullName);
                arguments[i] = manager.ReadRegisterPrimitiveValue(argtype.IsPrimitive ? argtype : typeof(uint), sp_offset);

                if (!argtype.IsPrimitive)
                {
                    arguments[i] = manager.ReadObjectFromLS((uint)arguments[i]);
                }

                sp_offset += 16;
            }

            if (calledmethod.Name != "WriteLine" && calledmethod.Name != "Format" && calledmethod.Name != "ToString")
            {
                Console.WriteLine("Invoking {0} with arguments: ", calledmethod.DeclaringType.FullName + "::" + calledmethod.Name);
                foreach (object o in arguments)
                {
                    Console.WriteLine("\t{0}", o == null ? "<null>" : o.ToString());
                }
            }

            object result      = m.Invoke(@this, arguments);
            int    resultIndex = result == null ? 0 : -1;

            foreach (KeyValuePair <uint, object> t in manager.KnownObjectsById)
            {
                if (t.Value != null)
                {
                    //Strings are imutable, so there is no reason to transfer them back
                    if (manager.ObjectTable[t.Key].KnownType == AccCIL.KnownObjectTypes.String)
                    {
                        if (t.Value.Equals(result))
                        {
                            resultIndex = (int)t.Key;
                        }
                        continue;
                    }

                    manager.WriteObjectToLS(t.Key, t.Value);

                    if (t.Value == result)
                    {
                        resultIndex = (int)t.Key;
                    }
                }
            }

            if (m.ReturnType != null)
            {
                if (m.ReturnType.IsPrimitive)
                {
                    manager.WriteRegisterPrimitiveValue(result, arg_base);
                }
                else
                {
                    if (resultIndex < 0)
                    {
                        resultIndex = (int)manager.CreateObjectOnLS(result);
                        manager.ObjectTable[(uint)resultIndex].Refcount = 1;
                        manager.SaveObjectTable();
                    }

                    manager.WriteRegisterPrimitiveValue((uint)resultIndex, arg_base);
                }
            }

            return(true);
        }
示例#2
0
            public byte[] Serialize(object element, out uint size)
            {
                if (element == null)
                {
                    throw new ArgumentNullException("element");
                }

                Array arr    = (Array)element;
                Type  eltype = element.GetType().GetElementType();

                AccCIL.KnownObjectTypes objt;
                uint   elsize;
                string typename;

                if (eltype.IsPrimitive)
                {
                    objt     = AccCIL.AccCIL.GetObjType(eltype);
                    elsize   = 1u << (int)BuiltInSPEMethods.get_array_elem_len_mult((uint)objt);
                    typename = null;
                }
                else
                {
                    elsize   = 4;
                    objt     = AccCIL.KnownObjectTypes.Object;
                    typename = element.GetType().FullName;
                }

                size = (uint)arr.Length * elsize;
                uint alignedSize = ((size + 15) >> 4) << 4;

                SPEEmulator.EndianBitConverter c = new SPEEmulator.EndianBitConverter(new byte[alignedSize]);

                if (eltype.IsPrimitive)
                {
                    ISerializer elserializer;
                    m_parent.Serializers.TryGetValue(eltype, out elserializer);
                    if (elserializer == null)
                    {
                        throw new Exception("Unsupported inner type: " + eltype.FullName);
                    }

                    for (int i = 0; i < arr.Length; i++)
                    {
                        //TODO: This is inefficient, it should write directly into the target buffer
                        uint   s;
                        byte[] localdata = elserializer.Serialize(arr.GetValue(i), out s);
                        Array.Copy(localdata, 0, c.Data, c.Position, localdata.Length);
                        c.Position += s;
                    }
                }
                else
                {
                    for (int i = 0; i < arr.Length; i++)
                    {
                        object value = arr.GetValue(i);
                        if (value == null)
                        {
                            c.WriteUInt(0);
                        }
                        else
                        {
                            //If we are writing back the array, write back the element as well
                            if (m_parent.KnownObjectsByObj.ContainsKey(element) && m_parent.KnownObjectsByObj.ContainsKey(value))
                            {
                                m_parent.WriteObjectToLS(m_parent.KnownObjectsByObj[value], value);
                            }
                            else
                            {
                                c.WriteUInt(m_parent.CreateObjectOnLS(value));
                            }
                        }
                    }
                }

                return(c.Data);
            }